├── .gitignore ├── admin-ui.php ├── assets ├── css │ └── feedwordpress-elements.css ├── images │ ├── banner-1544x500.jpg │ ├── banner-772x250.jpg │ ├── btc-qr-128px.png │ ├── btc-qr-64px.png │ ├── btc-qr.png │ ├── fav-top.png │ ├── fav.png │ ├── feedwordpress.png │ ├── icon-128x128.png │ ├── icon-256x256.png │ ├── icon.ai │ ├── icon.svg │ ├── paypal-donation-64px.png │ ├── screenshot-1.png │ ├── screenshot-2.png │ ├── screenshot-3.png │ └── screenshot-4.png └── js │ └── feedwordpress-elements.js ├── authors-page.php ├── categories-page.php ├── compatability.php ├── diagnostics-page.php ├── extend └── SimplePie │ ├── 1.3.1 │ ├── feedwordpie_item.class.php │ └── feedwordpie_parser.class.php │ ├── SimplePie_Cache │ └── feedwordpie_cache.class.php │ ├── default │ ├── feedwordpie_cache.class.php │ ├── feedwordpie_item.class.php │ └── feedwordpie_parser.class.php │ ├── feedwordpie.class.php │ ├── feedwordpie_cache.class.php │ ├── feedwordpie_content_type_sniffer.class.php │ ├── feedwordpie_file.class.php │ ├── feedwordpie_item.class.php │ └── feedwordpie_parser.class.php ├── externals └── myphp │ └── myphp.class.php ├── feedfinder.class.php ├── feeds-page.php ├── feedtime.class.php ├── feedwordpress-walker-category-checklist.class.php ├── feedwordpress.php ├── feedwordpress.pings.functions.php ├── feedwordpress.wp-admin.post-edit.functions.php ├── feedwordpressadminpage.class.php ├── feedwordpressboilerplatereformatter.class.php ├── feedwordpressboilerplatereformatter.shortcode.functions.php ├── feedwordpressdiagnostic.class.php ├── feedwordpresshtml.class.php ├── feedwordpresshttpauthenticator.class.php ├── feedwordpresslocalpost.class.php ├── feedwordpressparsedpostmeta.class.php ├── feedwordpressrpc.class.php ├── feedwordpresssettingsui.class.php ├── feedwordpresssyndicationpage.class.php ├── inspectpostmeta.class.php ├── magpiefromsimplepie.class.php ├── magpiemocklink.class.php ├── performance-page.php ├── posts-page.php ├── readme.txt ├── syndicatedlink.class.php ├── syndicatedpost.class.php ├── syndicatedpostterm.class.php ├── syndicatedpostxpathquery.class.php ├── syndication.php ├── syndicationdataqueries.class.php ├── template-functions.php ├── templates └── notice-debug-mode-yes.html.php └── updatedpostscontrol.class.php /.gitignore: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # Subversion Repository for the benefit of the WordPress overlords. # 3 | ##################################################################### 4 | 5 | .svn 6 | *(*conflicted copy*)* 7 | 8 | # Stupid macOS temporary files 9 | 10 | # General 11 | .DS_Store 12 | .AppleDouble 13 | .LSOverride 14 | 15 | # Icon must end with two \r 16 | Icon 17 | 18 | 19 | Icon? 20 | 21 | # Thumbnails 22 | ._* 23 | 24 | # Files that might appear in the root of a volume 25 | .DocumentRevisions-V100 26 | .fseventsd 27 | .Spotlight-V100 28 | .TemporaryItems 29 | .Trashes 30 | .VolumeIcon.icns 31 | .com.apple.timemachine.donotpresent 32 | 33 | # Directories potentially created on remote AFP share 34 | .AppleDB 35 | .AppleDesktop 36 | Network Trash Folder 37 | Temporary Items 38 | .apdisk 39 | 40 | # Stuff from the Nova editor 41 | .nova 42 | node_modules 43 | package.json 44 | package-lock.json 45 | .eslintrc.yml 46 | -------------------------------------------------------------------------------- /assets/css/feedwordpress-elements.css: -------------------------------------------------------------------------------- 1 | /* Category widget */ 2 | .feedwordpress-category-div .tabs-panel { 3 | height: 200px; 4 | overflow: auto; 5 | border: 1px solid #dfdfdf; 6 | margin-left: 126px; 7 | } 8 | .feedwordpress-category-div ul.category-tabs { 9 | float: left; 10 | margin: 0 -120px 0 5px; 11 | padding: 0; 12 | text-align: right; 13 | width: 120px; 14 | } 15 | .feedwordpress-category-div ul.category-tabs li.tabs { 16 | display: block; 17 | border-radius: 3px 0 0 3px; 18 | border-color: #dfdfdf; 19 | border-style: solid none solid solid; 20 | border-width: 1px 0 1px 1px; 21 | margin-right: -1px; 22 | padding: 8px; 23 | background-color: #f1f1f1; 24 | } 25 | 26 | .feedwordpress-category-div ul.categorychecklist ul { 27 | margin-left: 18px; 28 | } 29 | .feedwordpress-category-div ul.category-tabs a { 30 | color: #333333; 31 | font-weight: bold; 32 | text-decoration: none; 33 | } 34 | 35 | /* Common settings page elements */ 36 | #fwpfs-container { 37 | margin: 11px 12px 0; 38 | min-width: 130px; 39 | position: relative; 40 | } 41 | #fwpfs-container .subsubsub { 42 | float: none !important; 43 | } 44 | .tablenav p.submit { 45 | margin: 0px; 46 | padding: 0px; 47 | } 48 | .fwpfs { 49 | color: #dddddd !important; 50 | background-color: #333 !important; 51 | background-color: #797979; 52 | border-color: #777777 #777777 #666666 !important; 53 | border-radius: 12px; 54 | -moz-border-radius: 12px; 55 | -webkit-border-radius: 12px; 56 | border-style: solid; 57 | border-width: 1px; 58 | line-height: 15px; 59 | padding: 3px 30px 4px 12px; 60 | } 61 | .fwpfs.slide-down { 62 | border-bottom-color: #626262; 63 | border-top-left-radius: 12px; 64 | border-top-right-radius: 12px; 65 | border-bottom-left-radius: 0; 66 | border-bottom-right-radius: 0; 67 | -webkit-border-top-left-radius: 12px; 68 | -webkit-border-top-right-radius: 12px; 69 | -webkit-border-bottom-left-radius: 0; 70 | -webkit-border-bottom-right-radius: 0; 71 | -moz-border-radius-topleft: 12px; 72 | -moz-border-radius-topright: 12px; 73 | -moz-border-radius-bottomleft: 0; 74 | -moz-border-radius-bottomright: 0; 75 | border-bottom-style: solid; 76 | border-bottom-width: 1px; 77 | } 78 | 79 | .current-setting { 80 | display: block; 81 | font-size: smaller; 82 | margin-left: 2em; 83 | font-size: smaller; 84 | } 85 | .twofer tr td h4 { 86 | margin-top: 0px; 87 | margin-bottom: 3px; 88 | } 89 | ul.current-setting { 90 | list-style: disc outside; 91 | padding-left: 2em; 92 | } 93 | 94 | /* Switchfeed interface elements */ 95 | 96 | #feed-finder form { 97 | padding-bottom: 2em; 98 | border-bottom: 1px dashed #333; 99 | margin-bottom: 2em; 100 | } 101 | #feed-finder form.multi .inside { 102 | margin-left: 1em; 103 | border-left: 3px solid #333; 104 | padding-left: 2em; 105 | } 106 | 107 | #feed-finder form fieldset { 108 | clear: both; 109 | border: 1px solid #777; 110 | padding: 5px 25px; 111 | background-color: #fff; 112 | border-radius: 5px; 113 | -moz-border-radius: 5px; 114 | -webkit-border-radius: 5px; 115 | } 116 | #feed-finder form fieldset.alt { 117 | background-color: #eee; 118 | } 119 | #feed-finder form fieldset.current { 120 | background-color: #efe; 121 | } 122 | #feed-finder form fieldset.current legend { 123 | background-color: #7f7; 124 | } 125 | #feed-finder form fieldset legend { 126 | border-left: 1px solid #777; 127 | border-right: 1px solid #777; 128 | border-top: 1px solid #777; 129 | border-bottom: 1px solid #777; 130 | border-radius: 5px; 131 | -moz-border-radius: 5px; 132 | -webkit-border-radius: 5px; 133 | background-color: #7ff; 134 | padding: 3px 10px; 135 | font-weight: bold; 136 | } 137 | #feed-finder form fieldset label { 138 | font-weight: bold; 139 | } 140 | #feed-finder form fieldset div.submit { 141 | clear: both; 142 | text-align: left; 143 | } 144 | #feed-finder form fieldset div.submit input { 145 | margin-right: 3em; 146 | } 147 | 148 | #feed-finder .feed-sample { 149 | float: right; 150 | background-color: #d0d0d0; 151 | color: black; 152 | width: 45%; 153 | font-size: 70%; 154 | border-left: 1px dotted #a0a0a0; 155 | margin-left: 1em; 156 | padding: 3px; 157 | max-height: 200px; 158 | overflow: auto; 159 | } 160 | #feed-finder .feed-sample p, 161 | .feed-sample h3 { 162 | padding-left: 0.5em; 163 | padding-right: 0.5em; 164 | } 165 | #feed-finder .feed-sample .feed-problem { 166 | background-color: #ffd0d0; 167 | border-bottom: 1px dotted black; 168 | padding-bottom: 0.5em; 169 | margin-bottom: 0.5em; 170 | } 171 | 172 | table.edit-form { 173 | width: 100%; 174 | } 175 | table.edit-form th { 176 | width: 27%; 177 | vertical-align: top; 178 | text-align: right; 179 | padding: 0.5em; 180 | } 181 | table.edit-form th .setting-description { 182 | font-weight: normal; 183 | font-size: smaller; 184 | font-style: italic; 185 | } 186 | 187 | table.edit-form td { 188 | width: 73%; 189 | vertical-align: top; 190 | padding: 0.5em; 191 | } 192 | table.edit-form td ul.options { 193 | margin: 0; 194 | padding: 0; 195 | list-style: none; 196 | } 197 | table.edit-form td ul.options.compact li { 198 | display: inline; 199 | margin-left: 3em; 200 | white-space: nowrap; 201 | } 202 | table.edit-form.narrow th { 203 | width: 15%; 204 | } 205 | table.edit-form.narrow td { 206 | width: 85%; 207 | } 208 | table.edit-form td p { 209 | margin-top: 0px; 210 | } 211 | 212 | table.twofer { 213 | width: 100%; 214 | border: none; 215 | } 216 | table.twofer tr { 217 | vertical-align: top; 218 | } 219 | table.twofer td.equals.first { 220 | width: 49% !important; 221 | border-right: 1px dotted #777; 222 | padding-top: 0px; 223 | padding-bottom: 0px; 224 | padding-left: 0px; 225 | padding-right: 10px; 226 | } 227 | table.twofer td.equals.second { 228 | width: 49% !important; 229 | padding-top: 0px; 230 | padding-bottom: 0px; 231 | padding-left: 10px; 232 | padding-right: 0px; 233 | } 234 | 235 | table.twofer td.active { 236 | color: black; 237 | background-color: #cfc; 238 | border-radius: 5px; 239 | -moz-border-radius: 5px; 240 | -webkit-border-radius: 5px; 241 | } 242 | table.twofer td.inactive { 243 | color: #333; 244 | } 245 | table.twofer td.equals.first.active { 246 | border-right: none; 247 | } 248 | table.twofer td.equals.first.inactive { 249 | border-right: none; 250 | } 251 | 252 | table.twofer td.primary { 253 | width: 69%; 254 | border-right: 1px dotted #777; 255 | padding-right: 10px; 256 | } 257 | table.twofer td.secondary { 258 | padding-left: 10px; 259 | width: 30%; 260 | } 261 | 262 | #add-multiple-uri, 263 | #upload-opml { 264 | float: right; 265 | position: relative; 266 | width: 50%; 267 | background-color: #cfc; 268 | padding-left: 1em; 269 | padding-right: 1em; 270 | padding-top: 0.5em; 271 | padding-bottom: 0.5em; 272 | right: 0; 273 | top: auto; 274 | } 275 | #add-multiple-uri textarea { 276 | width: 100%; 277 | margin-top: 0.5em; 278 | } 279 | #add-multiple-uri h4 { 280 | margin-bottom: 2px; 281 | margin-top: 0px; 282 | border-bottom: 1px dotted black; 283 | } 284 | 285 | #dashboard-widgets #feedwordpress_dashboard h4 { 286 | color: #777777; 287 | font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; 288 | font-size: 13px; 289 | font-style: italic; 290 | font-weight: normal; 291 | margin: 0px; 292 | border-bottom: 1px solid #ececec; 293 | padding-left: 15px; 294 | padding-top: 10px; 295 | padding-bottom: 5px; 296 | padding-right: 0px; 297 | } 298 | 299 | #feedwordpress_dashboard .feedwordpress-stats { 300 | width: 49%; 301 | } 302 | #feedwordpress_dashboard .feedwordpress-stats table { 303 | margin-top: 5px; 304 | margin-left: 15px; 305 | } 306 | #feedwordpress_dashboard .feedwordpress-actions ul.options { 307 | margin-left: 15px !important; 308 | margin-top: 5px !important; 309 | } 310 | 311 | #feedwordpress_dashboard .feedwordpress-actions { 312 | width: 49%; 313 | float: right; 314 | } 315 | #feedwordpress_dashboard td.b { 316 | padding-right: 12px; 317 | } 318 | #feedwordpress_dashboard td.b a { 319 | font-size: 18px; 320 | } 321 | 322 | #feedwordpress_dashboard td.t.active a:link, 323 | #feedwordpress_dashboard td.t.active a:visited { 324 | color: green; 325 | } 326 | #feedwordpress_dashboard td.t.inactive a:link, 327 | #feedwordpress_dashboard td.t.inactive a:visited { 328 | color: red; 329 | } 330 | 331 | #feedwordpress_dashboard #add-single-uri { 332 | clear: both; 333 | margin-top: 15px; 334 | } 335 | 336 | #feedwordpress_dashboard #add-single-uri #syndicated-links { 337 | border-top: 1px solid #ececec; 338 | width: 49%; 339 | } 340 | #feedwordpress_dashboard #add-single-uri #syndicated-links .container { 341 | margin-top: 5px; 342 | margin-left: 15px; 343 | } 344 | 345 | #feedwordpress_dashboard #add-single-uri #check-for-updates { 346 | border-top: 1px solid #ececec; 347 | float: right; 348 | text-align: left; 349 | width: 49%; 350 | } 351 | #feedwordpress_dashboard #add-single-uri #check-for-updates .container { 352 | margin-top: 5px; 353 | margin-left: 15px; 354 | } 355 | #multiadd-status { 356 | position: absolute; 357 | padding: 10px; 358 | background-color: #ecec70; 359 | border-radius: 10px; 360 | -moz-border-radius: 10px; 361 | -webkit-border-radius: 10px; 362 | opacity: 0.85; 363 | top: auto; 364 | left: 45%; 365 | right: auto; 366 | bottom: -5px; 367 | } 368 | #multiadd-form { 369 | position: relative; 370 | padding-bottom: 3em; 371 | } 372 | #multiadd-status img { 373 | vertical-align: middle; 374 | } 375 | #multiadd-list { 376 | border-top: 1px dotted black; 377 | padding-top: 5px; 378 | padding-bottom: 5px; 379 | border-bottom: 1px dotted black; 380 | } 381 | #multiadd-buttons { 382 | position: absolute; 383 | bottom: 0px; 384 | margin-top: 15px; 385 | margin-left: 15px; 386 | } 387 | 388 | .feedwordpress-admin { 389 | position: relative; 390 | } 391 | .feedwordpress-admin .submit { 392 | position: relative; 393 | z-index: 40; 394 | } 395 | 396 | /* These icons have been deprecated since 2013 or so; 397 | see https://core.trac.wordpress.org/ticket/26119. 398 | Nevertheless, we need proper sizing for the 'new' SVG. 399 | (gwyneth 20210717) */ 400 | .feedwordpress-admin .icon32, 401 | .feedwordpress-admin .icon32 img { 402 | width: 32px; 403 | height: 32px; 404 | } 405 | 406 | #feedwordpress-admin-syndication .heads-up { 407 | background-color: #d0d0d0; 408 | color: black; 409 | padding: 1em; 410 | margin: 0.5em 4em !important; 411 | } 412 | #feedwordpress-admin-syndication .update-form.with-donation { 413 | margin-right: 50%; 414 | min-height: 355px; 415 | } 416 | #feedwordpress-admin-syndication #feedwordpress_update_box .inside { 417 | display: flex; 418 | flex-direction: row-reverse; 419 | } 420 | #feedwordpress-admin-syndication .donation-form, 421 | #feedwordpress-admin-syndication .donation-thanks { 422 | background-color: #ffffcc; 423 | text-align: left; 424 | padding: 0.5em 0.5em; 425 | border-left: thin dashed #777777; 426 | font-size: 70%; 427 | width: 50%; 428 | } 429 | #feedwordpress-admin-syndication .donation-thanks { 430 | background-color: #ccffcc; 431 | } 432 | #feedwordpress-admin-syndication .donation-thanks .signature { 433 | text-align: right; 434 | font-style: italic; 435 | } 436 | #feedwordpress-admin-syndication .donation-form h4, 437 | #feedwordpress-admin-syndication .donation-thanks h4 { 438 | font-size: 10px; 439 | text-align: center; 440 | border-bottom: 1px solid #777777; 441 | margin: 0px; 442 | } 443 | #feedwordpress-admin-syndication .donation-form .donate { 444 | text-align: center; 445 | } 446 | #feedwordpress-admin-syndication .donation-form .sod-off { 447 | padding-top: 0.5em; 448 | margin-top: 0.5em; 449 | border-top: thin solid #777777; 450 | } 451 | #feedwordpress-admin-syndication .feed-missing { 452 | background-color: #ffffd0; 453 | } 454 | #feedwordpress-admin-syndication .unsubscribed tr { 455 | background-color: #ffe0e0; 456 | } 457 | #feedwordpress-admin-syndication .unsubscribed tr.alternate { 458 | background-color: #fff0f0; 459 | } 460 | #feedwordpress-admin-syndication tr.feed-error { 461 | background-color: #ffffd0; 462 | } 463 | 464 | #feedwordpress-admin-feeds .add-remove, 465 | .feedwordpress-admin .remove-it { 466 | padding-left: 1.5em; 467 | font-size: 0.8em; 468 | text-transform: uppercase; 469 | text-decoration: none !important; 470 | vertical-align: middle; 471 | } 472 | 473 | #link-rss-userpass-use, 474 | .link-rss-authentication table { 475 | display: block; 476 | font-size: 75%; 477 | white-space: nowrap; 478 | padding: 0.5em 0; 479 | } 480 | #feed-finder .link-rss-authentication table { 481 | font-size: inherit; 482 | } 483 | 484 | #link-rss-authentication label { 485 | font-weight: bold; 486 | padding-left: 1.5em; 487 | } 488 | #link-rss-authentication td { 489 | width: 25%; 490 | } 491 | 492 | #feedwordpress-admin-feeds .link-rss-params-row { 493 | vertical-align: middle; 494 | } 495 | #feedwordpress-admin-feeds .link-rss-params-remove, 496 | .feedwordpress-admin .remove-it { 497 | display: block; 498 | padding-left: 0em !important; 499 | margin-top: 7px; 500 | color: #777; 501 | } 502 | 503 | #feedwordpress-admin-feeds .link-rss-params-remove:hover, 504 | .feedwordpress-admin .remove-it:hover { 505 | color: #aa3030; 506 | } 507 | 508 | #feedwordpress-admin-feeds .link-rss-params-remove .x, 509 | .feedwordpress-admin .remove-it .x { 510 | cursor: pointer; 511 | display: block; 512 | float: left; 513 | width: 10px; 514 | height: 10px; 515 | margin-right: 2px; 516 | overflow: hidden; 517 | text-indent: -9999px; 518 | } 519 | 520 | #feedwordpress-admin-feeds #link-rss-params td { 521 | width: auto !important; 522 | } 523 | 524 | /* Feed Contents picker & XPath test results widgets */ 525 | 526 | .fwp-xpath-test-results { 527 | position: absolute; 528 | top: auto; 529 | left: auto; 530 | z-index: 9999999; 531 | overflow: auto; 532 | max-height: 100px; 533 | max-width: 400px; 534 | background-color: #ccffcc; 535 | padding: 10px; 536 | } 537 | .fwp-xpath-test-results-close { 538 | position: absolute; 539 | top: 10px; 540 | right: 10px; 541 | } 542 | .fwp-xpath-test-setting { 543 | font-size: smaller; 544 | } 545 | 546 | .fwp-feed-contents-picker h4, 547 | .fwp-xpath-test-results h4 { 548 | margin-top: 0; 549 | margin-bottom: 5px; 550 | border-bottom: 1px dotted black; 551 | } 552 | .fwp-feed-contents-picker-close { 553 | position: absolute; 554 | top: 10px; 555 | right: 10px; 556 | } 557 | .fwp-feed-contents-picker, 558 | .fwp-feeds-picker { 559 | position: absolute; 560 | top: auto; 561 | left: auto; 562 | z-index: 9999999; 563 | overflow: auto; 564 | max-height: 100px; 565 | max-width: 400px; 566 | background-color: #ccffcc; 567 | padding: 10px; 568 | } 569 | 570 | .hovered-component .hover-on { 571 | display: none; 572 | } 573 | .hovered-component:hover .hover-on { 574 | display: inline; 575 | } 576 | .hovered-component:hover .hover-on.pop-over { 577 | display: block; 578 | position: absolute; 579 | } 580 | 581 | /* 582 | * Getting rid of the ugly tiny PNGs and replacing it with WP Dashicons 583 | * (gwyneth 20210717) 584 | */ 585 | .feedwordpress-dashicons /*, 586 | .feedwordpress-dashicons:before */{ 587 | width: 18px; 588 | height: 18px; 589 | font-size: 18px; 590 | background-color: transparent; 591 | color: green; 592 | } 593 | /* Removes all colouring from a button; used to create a button out of a WP Dashicon. 594 | (gwyneth 20210717) */ 595 | .feedwordpress-dashicons-button { 596 | color: green; 597 | background: transparent; 598 | border: none !important; 599 | box-shadow: none !important; 600 | text-shadow: none !important; 601 | cursor: pointer; 602 | } 603 | .feedwordpress-dashicons:hover, 604 | .feedwordpress-dashicons-button:hover { 605 | background-color: transparent; 606 | color: #4caf50 !important; 607 | /* text-shadow: 0px 0px 3px lightgrey; */ 608 | cursor: pointer; 609 | } 610 | 611 | /* 612 | * Attempting to change the padding on the SVG (gwyneth 20210718) 613 | */ 614 | li#toplevel_page_feedwordpress-syndication .wp-menu-image img { 615 | padding: 0; 616 | margin-top: 0; /* added this for good measure */ 617 | } 618 | 619 | /* This is to avoid that Dashicons get underlines! (gwyneth 20210718) */ 620 | .fwp-no-underline, .fwp-no-underline:hover { 621 | text-decoration: none; 622 | } -------------------------------------------------------------------------------- /assets/images/banner-1544x500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/banner-1544x500.jpg -------------------------------------------------------------------------------- /assets/images/banner-772x250.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/banner-772x250.jpg -------------------------------------------------------------------------------- /assets/images/btc-qr-128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/btc-qr-128px.png -------------------------------------------------------------------------------- /assets/images/btc-qr-64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/btc-qr-64px.png -------------------------------------------------------------------------------- /assets/images/btc-qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/btc-qr.png -------------------------------------------------------------------------------- /assets/images/fav-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/fav-top.png -------------------------------------------------------------------------------- /assets/images/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/fav.png -------------------------------------------------------------------------------- /assets/images/feedwordpress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/feedwordpress.png -------------------------------------------------------------------------------- /assets/images/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/icon-128x128.png -------------------------------------------------------------------------------- /assets/images/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/icon-256x256.png -------------------------------------------------------------------------------- /assets/images/icon.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/icon.ai -------------------------------------------------------------------------------- /assets/images/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/paypal-donation-64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/paypal-donation-64px.png -------------------------------------------------------------------------------- /assets/images/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/screenshot-1.png -------------------------------------------------------------------------------- /assets/images/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/screenshot-2.png -------------------------------------------------------------------------------- /assets/images/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/screenshot-3.png -------------------------------------------------------------------------------- /assets/images/screenshot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radgeek/feedwordpress/9cc47cf8d13d885b377754e0ceb65babcd906c0a/assets/images/screenshot-4.png -------------------------------------------------------------------------------- /compatability.php: -------------------------------------------------------------------------------- 1 | = $floor ); 29 | if ( ! is_null( $ceiling ) ) : 30 | $good = ( $good and ( $ver < $ceiling ) ); 31 | endif; 32 | return $good; 33 | } /* FeedWordPressCompatibility::test_version() */ 34 | 35 | /** 36 | * Creates a new category for the Links. 37 | * 38 | * WP dropped support for "Links". 39 | * 40 | * @param string $name New link category name. 41 | * 42 | * @return mixed Most of the time should return an array with `term_id` 43 | * and `term_taxonomy_id`, unless there was an error. 44 | */ 45 | static function insert_link_category( $name ) { 46 | // WordPress 2.3+ term/taxonomy API 47 | $term = wp_insert_term( $name, 'link_category' ); 48 | 49 | // OK: returned array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id) 50 | if ( ! is_wp_error( $term ) ) : 51 | $cat_id = $term['term_id']; 52 | 53 | // Error: term with this name already exists. Well, let's use that then. 54 | elseif ( 'term_exists' == $term->get_error_code() ) : 55 | // Already-existing term ID is returned in data field 56 | $cat_id = $term->get_error_data( 'term_exists' ); 57 | 58 | // Error: another kind of error, harder to recover from. Return WP_Error. 59 | else : 60 | $cat_id = $term; 61 | endif; 62 | 63 | // Return newly-created category ID 64 | return $cat_id; 65 | } /* FeedWordPressCompatibility::insert_link_category () */ 66 | 67 | /** 68 | * Returns category id for a Links category. 69 | * 70 | * "Links" became optional in WP. 71 | * 72 | * For the explanation of the values, see @see term_exists() 73 | * 74 | * @param int|string $value @see term_exists() 75 | * @param string $key Unused. 76 | * @return mixed @see term_exists() 77 | */ 78 | static function link_category_id( $value, $key = 'cat_name' ) { 79 | $cat_id = NULL; 80 | 81 | $the_term = term_exists( $value, 'link_category' ); 82 | 83 | // Sometimes, in some versions, we get a row 84 | if ( is_array( $the_term ) ) : 85 | $cat_id = $the_term['term_id']; 86 | 87 | // other times we get an integer result 88 | else : 89 | $cat_id = $the_term; 90 | endif; 91 | 92 | return $cat_id; 93 | } /* FeedWordPressCompatibility::link_category_id () */ 94 | 95 | /** 96 | * Validate if the user has the right capability for doing this request. 97 | * 98 | * @see check_admin_referer() 99 | * @see current_user_can() 100 | * 101 | * @param int|string $action The nonce action. 102 | * @param string|null $capability Capability name. 103 | */ 104 | static function validate_http_request( $action = -1, $capability = null ) { 105 | // Only worry about this if we're using a method with significant side-effects 106 | if ( 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) : 107 | // Limit post by user capabilities 108 | if ( ! is_null( $capability ) and ! current_user_can( $capability ) ) : 109 | wp_die( esc_html__( 'Cheatin’ uh?' ) ); 110 | endif; 111 | 112 | // If check_admin_referer() checks a nonce. 113 | if ( function_exists( 'wp_verify_nonce' ) ) : 114 | check_admin_referer( $action ); 115 | 116 | // No nonces means no checking nonces. 117 | else : 118 | check_admin_referer(); 119 | endif; 120 | endif; 121 | } /* FeedWordPressCompatibility::validate_http_request() */ 122 | 123 | /** 124 | * Stamps form with hidden fields for a nonce in WP 2.0.3 & later. 125 | * 126 | * Basically just checks if the function wp_nonce_field() exists, and, if so, 127 | * uses it; on earlier WP versions, just skips it. 128 | * 129 | * @todo What about the HTML which might get returned by wp_nonce_field()? 130 | * (gwyneth 20230917) 131 | * 132 | * @see wp_nonce_field() 133 | * 134 | * @param int|string $action Optional action name, defaults to -1. 135 | * 136 | */ 137 | static function stamp_nonce( $action = -1 ) { 138 | if ( function_exists( 'wp_nonce_field' ) ) : 139 | wp_nonce_field( $action ); 140 | endif; 141 | } /* FeedWordPressCompatibility::stamp_nonce() */ 142 | 143 | static function bottom_script_hook ($filename) { 144 | global $fwp_path; 145 | 146 | $hook = 'admin_footer-'.$fwp_path.'/'.basename($filename); 147 | return $hook; 148 | } /* FeedWordPressCompatibility::bottom_script_hook() */ 149 | } /* class FeedWordPressCompatibility */ 150 | 151 | // Compat 152 | 153 | if ( ! function_exists( 'set_post_field' ) ) { 154 | /** 155 | * Update data from a post field based on Post ID. 156 | * 157 | * Examples of the post field will be, 'post_type', 'post_status', 'post_content', etc. 158 | * 159 | * The context values are based off of the taxonomy filter functions and 160 | * supported values are found within those functions. 161 | * 162 | * @uses sanitize_post_field() 163 | * 164 | * @param string $field Post field name. 165 | * @param mixed $value New value for post field. 166 | * @param id $post Post ID. 167 | * @return bool Result of UPDATE query. 168 | * 169 | * Included under terms of GPL from WordPress Ticket #10946 170 | */ 171 | function set_post_field ($field, $value, $post_id) { 172 | global $wpdb; 173 | 174 | $post_id = absint($post_id); 175 | // sigh ... when FWP is active, I need to avoid avoid_kses_munge 176 | // $value = sanitize_post_field($field, $value, $post_id, 'db'); 177 | return $wpdb->update($wpdb->posts, array($field => $value), array('ID' => $post_id)); 178 | } /* function set_post_field () */ 179 | 180 | } /* if */ 181 | 182 | if ( ! function_exists( 'is_countable' ) ) { 183 | /* Copied from WordPress 5.3.2 wp-includes/compat.php pursuant to terms 184 | * of GPL. Provide support for is_countable() for versions of PHP < 7.3 185 | * and for versions of WordPress < 4.9.6. -C.J. 2020/01/24 186 | */ 187 | 188 | /** 189 | * Polyfill for is_countable() function added in PHP 7.3. 190 | * 191 | * Verify that the content of a variable is an array or an object 192 | * implementing the Countable interface. 193 | * 194 | * @since 4.9.6 195 | * 196 | * @param mixed $var The value to check. 197 | * 198 | * @return bool True if `$var` is countable, false otherwise. 199 | */ 200 | function is_countable( $var ) { 201 | return ( is_array( $var ) 202 | || $var instanceof Countable 203 | || $var instanceof SimpleXMLElement 204 | || $var instanceof ResourceBundle 205 | ); 206 | } 207 | } /* if */ 208 | 209 | require_once dirname(__FILE__) . '/feedwordpress-walker-category-checklist.class.php'; 210 | 211 | /** 212 | * Checks if we have all the categories we need. 213 | * 214 | * @see wp_terms_checklist() 215 | * 216 | * @param int $post_id Optional, defaults to zero. 217 | * @param int $descendents_and_self @see wp_terms_checklist() 218 | * @param bool $selected_cats @see wp_terms_checklist() 219 | * @param string|array $params @see wp_terms_checklist() 220 | * 221 | * @uses wp_terms_checklist() 222 | * @uses FeedWordPress_Walker_Category_Checklist() 223 | */ 224 | function fwp_category_checklist( $post_id = 0, $descendents_and_self = 0, $selected_cats = false, $params = array() ) { 225 | if ( is_string( $params ) ) : 226 | $prefix = $params; 227 | $taxonomy = 'category'; 228 | elseif ( is_array( $params ) ) : 229 | $prefix = ( isset( $params['prefix'] ) ? $params['prefix'] : '' ); 230 | $taxonomy = ( isset( $params['taxonomy'] ) ? $params['taxonomy'] : 'category' ); 231 | endif; 232 | 233 | $walker = new FeedWordPress_Walker_Category_Checklist( $params ); 234 | $walker->set_prefix( $prefix ); 235 | $walker->set_taxonomy( $taxonomy ); 236 | wp_terms_checklist( /*post_id=*/ $post_id, array( 237 | 'taxonomy' => $taxonomy, 238 | 'descendents_and_self' => $descendents_and_self, 239 | 'selected_cats' => $selected_cats, 240 | 'popular_cats' => false, 241 | 'walker' => $walker, 242 | 'checked_ontop' => true, 243 | ) ); 244 | } /* function fwp_category_checklist() */ 245 | 246 | /** 247 | * Calculates the difference between a timestamp and the current time. 248 | * 249 | * @param int $ts Timestamp. 250 | * 251 | * @return string A human-readable indication of the elapsed time. 252 | */ 253 | function fwp_time_elapsed( $ts ) { 254 | if ( ! is_int( $ts ) ) : 255 | 256 | endif; 257 | if ( function_exists( 'human_time_diff' ) ) : 258 | if ( $ts >= time() ) : 259 | $ret = human_time_diff( $ts ) . __( " from now" ); 260 | else : 261 | $ret = human_time_diff( $ts ) . __( " ago" ); 262 | endif; 263 | else : 264 | // $ret = strftime( '%x %X', $ts ); // deprecated 265 | $ret = date( "Y-m-d H:i:s", $ts ); 266 | endif; 267 | return $ret; 268 | } /* function fwp_time_elapsed() */ 269 | 270 | /** 271 | * UPGRADE INTERFACE: Have users upgrade DB from older versions of FWP. 272 | * 273 | * @uses FeedWordPress 274 | * @uses FeedWordPress::upgrade_database() 275 | * @uses get_option() 276 | * @uses MyPHP::post() 277 | */ 278 | function fwp_upgrade_page() { 279 | if ( 'Upgrade' == MyPHP::post( 'action' ) ) : 280 | /** @var string Current FeedWordPress version. */ 281 | $ver = get_option( 'feedwordpress_version' ); 282 | if ( ! empty( $ver ) and FEEDWORDPRESS_VERSION != $ver ) : 283 | echo "
\n"; 284 | echo "

" . esc_html__( "Upgrading FeedWordPress..." ) . "

"; 285 | 286 | $feedwordpress = new FeedWordPress; 287 | $feedwordpress->upgrade_database( $ver ); 288 | echo "

" . esc_html__( "Done!" ) . " " . esc_html__( "Upgraded database to version " ) . esc_html( FEEDWORDPRESS_VERSION ) . ".

\n"; 289 | echo "
\n"; 290 | echo "
"; 291 | echo "
\n"; 292 | echo "
\n"; 293 | return; 294 | else : 295 | echo "

" . esc_html__( "Already at version " ) . esc_html( FEEDWORDPRESS_VERSION ) . "!

"; 296 | endif; 297 | endif; 298 | ?> 299 |
300 |

301 | 302 |

303 |

308 | 309 |

314 | 315 |

316 | 317 |
318 | 319 |
320 |
321 |
322 | namespace = array(''); 6 | $this->element = array(''); 7 | $this->xml_base = array(''); 8 | $this->xml_base_explicit = array(false); 9 | $this->xml_lang = array(''); 10 | $this->data = array(); 11 | $this->datas = array(array()); 12 | $this->current_xhtml_construct = -1; 13 | $this->xmlns_stack = array(); 14 | $this->xmlns_current = array(); 15 | 16 | // reset libxml parser 17 | xml_parser_free($xml); 18 | 19 | $xml = xml_parser_create_ns($this->encoding, $this->separator); 20 | xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); 21 | xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0); 22 | xml_set_object($xml, $this); 23 | xml_set_character_data_handler($xml, 'cdata'); 24 | xml_set_element_handler($xml, 'tag_open', 'tag_close'); 25 | xml_set_start_namespace_decl_handler($xml, 'start_xmlns'); 26 | } 27 | 28 | public function parse( &$data, $encoding, $url = '' ) { 29 | $data = apply_filters('feedwordpress_parser_parse', $data, $encoding, $this); 30 | 31 | // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character 32 | if (strtoupper($encoding) === 'US-ASCII') 33 | { 34 | $this->encoding = 'UTF-8'; 35 | } 36 | else 37 | { 38 | $this->encoding = $encoding; 39 | } 40 | 41 | // Strip BOM: 42 | // UTF-32 Big Endian BOM 43 | if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") 44 | { 45 | $data = substr($data, 4); 46 | } 47 | // UTF-32 Little Endian BOM 48 | elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") 49 | { 50 | $data = substr($data, 4); 51 | } 52 | // UTF-16 Big Endian BOM 53 | elseif (substr($data, 0, 2) === "\xFE\xFF") 54 | { 55 | $data = substr($data, 2); 56 | } 57 | // UTF-16 Little Endian BOM 58 | elseif (substr($data, 0, 2) === "\xFF\xFE") 59 | { 60 | $data = substr($data, 2); 61 | } 62 | // UTF-8 BOM 63 | elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") 64 | { 65 | $data = substr($data, 3); 66 | } 67 | 68 | if (substr($data, 0, 5) === '')) !== false) 69 | { 70 | $declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5))); 71 | if ($declaration->parse()) 72 | { 73 | $data = substr($data, $pos + 2); 74 | $data = 'version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data; 75 | } 76 | else 77 | { 78 | $this->error_string = 'SimplePie bug! Please report this!'; 79 | return false; 80 | } 81 | } 82 | 83 | $return = true; 84 | 85 | static $xml_is_sane = null; 86 | if ($xml_is_sane === null) 87 | { 88 | $parser_check = xml_parser_create(); 89 | xml_parse_into_struct($parser_check, '&', $values); 90 | xml_parser_free($parser_check); 91 | $xml_is_sane = isset($values[0]['value']); 92 | } 93 | 94 | // Create the parser 95 | if ($xml_is_sane) 96 | { 97 | $xml = xml_parser_create_ns($this->encoding, $this->separator); 98 | xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); 99 | xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0); 100 | xml_set_object($xml, $this); 101 | xml_set_character_data_handler($xml, 'cdata'); 102 | xml_set_element_handler($xml, 'tag_open', 'tag_close'); 103 | 104 | // Parse! 105 | $results = $this->do_xml_parse_attempt($xml, $data); 106 | $parseResults = $results[0]; 107 | $data = $results[1]; 108 | 109 | if ( ! $parseResults) { 110 | $this->error_code = xml_get_error_code($xml); 111 | $this->error_string = xml_error_string($this->error_code); 112 | $return = false; 113 | } 114 | $this->current_line = xml_get_current_line_number($xml); 115 | $this->current_column = xml_get_current_column_number($xml); 116 | $this->current_byte = xml_get_current_byte_index($xml); 117 | xml_parser_free($xml); 118 | return $return; 119 | } 120 | else 121 | { 122 | libxml_clear_errors(); 123 | $xml = new XMLReader(); 124 | $xml->xml($data); 125 | while (@$xml->read()) 126 | { 127 | switch ($xml->nodeType) 128 | { 129 | 130 | case constant('XMLReader::END_ELEMENT'): 131 | if ($xml->namespaceURI !== '') 132 | { 133 | $tagName = $xml->namespaceURI . $this->separator . $xml->localName; 134 | } 135 | else 136 | { 137 | $tagName = $xml->localName; 138 | } 139 | $this->tag_close(null, $tagName); 140 | break; 141 | case constant('XMLReader::ELEMENT'): 142 | $empty = $xml->isEmptyElement; 143 | if ($xml->namespaceURI !== '') 144 | { 145 | $tagName = $xml->namespaceURI . $this->separator . $xml->localName; 146 | } 147 | else 148 | { 149 | $tagName = $xml->localName; 150 | } 151 | $attributes = array(); 152 | while ($xml->moveToNextAttribute()) 153 | { 154 | if ($xml->namespaceURI !== '') 155 | { 156 | $attrName = $xml->namespaceURI . $this->separator . $xml->localName; 157 | } 158 | else 159 | { 160 | $attrName = $xml->localName; 161 | } 162 | $attributes[$attrName] = $xml->value; 163 | } 164 | 165 | $this->do_scan_attributes_namespaces($attributes); 166 | 167 | $this->tag_open(null, $tagName, $attributes); 168 | if ($empty) 169 | { 170 | $this->tag_close(null, $tagName); 171 | } 172 | break; 173 | case constant('XMLReader::TEXT'): 174 | 175 | case constant('XMLReader::CDATA'): 176 | $this->cdata(null, $xml->value); 177 | break; 178 | } 179 | } 180 | if ($error = libxml_get_last_error()) 181 | { 182 | $this->error_code = $error->code; 183 | $this->error_string = $error->message; 184 | $this->current_line = $error->line; 185 | $this->current_column = $error->column; 186 | return false; 187 | } 188 | else 189 | { 190 | return true; 191 | } 192 | } 193 | } /* FeedWordPie_Parser::parse() */ 194 | 195 | public function do_xml_parse_attempt ($xml, $data) { 196 | xml_set_start_namespace_decl_handler($xml, 'start_xmlns'); 197 | 198 | // Parse! 199 | $parseResults = xml_parse($xml, $data, true); 200 | $endOfJunk = strpos($data, ' 0) : 202 | // There is some junk before the feed prolog. Try to get rid of it. 203 | $data = substr($data, $endOfJunk); 204 | $data = trim($data); 205 | $this->reset_parser($xml); 206 | 207 | $parseResults = xml_parse($xml, $data, true); 208 | endif; 209 | 210 | $badEntity = (xml_get_error_code($xml) == 26); 211 | if ( ! $parseResults and $badEntity) : 212 | // There was an entity that libxml couldn't understand. 213 | // Chances are, it was a stray HTML entity. So let's try 214 | // converting all the named HTML entities to numeric XML 215 | // entities and starting over. 216 | $data = $this->html_convert_entities($data); 217 | $this->reset_parser($xml); 218 | 219 | $parseResults = xml_parse($xml, $data, true); 220 | endif; 221 | 222 | $result = array( 223 | $parseResults, 224 | $data 225 | ); 226 | return $result; 227 | 228 | } 229 | 230 | public function do_scan_attributes_namespaces ($attributes) { 231 | foreach ($attributes as $attr => $value) : 232 | list($ns, $local) = $this->split_ns($attr); 233 | if ($ns=='http://www.w3.org/2000/xmlns/') : 234 | if ('xmlns' == $local) : $local = false; endif; 235 | $this->start_xmlns(null, $local, $value); 236 | endif; 237 | endforeach; 238 | } 239 | 240 | var $xmlns_stack = array(); 241 | var $xmlns_current = array(); 242 | function tag_open ($parser, $tag, $attributes) { 243 | $ret = parent::tag_open($parser, $tag, $attributes); 244 | if ($this->current_xhtml_construct < 0) : 245 | $this->data['xmlns'] = $this->xmlns_current; 246 | $this->xmlns_stack[] = $this->xmlns_current; 247 | endif; 248 | return $ret; 249 | } 250 | 251 | function tag_close($parser, $tag) { 252 | if ($this->current_xhtml_construct < 0) : 253 | $this->xmlns_current = array_pop($this->xmlns_stack); 254 | endif; 255 | $ret = parent::tag_close($parser, $tag); 256 | return $ret; 257 | } 258 | 259 | function start_xmlns ($parser, $prefix, $uri) { 260 | if ( ! $prefix) : 261 | $prefix = ''; 262 | endif; 263 | if ($this->current_xhtml_construct < 0) : 264 | $this->xmlns_current[$prefix] = $uri; 265 | endif; 266 | 267 | return true; 268 | } /* FeedWordPie_Parser::start_xmlns() */ 269 | 270 | /* html_convert_entities($string) -- convert named HTML entities to 271 | * XML-compatible numeric entities. Adapted from code by @inanimatt: 272 | * https://gist.github.com/inanimatt/879249 273 | */ 274 | public function html_convert_entities($string) { 275 | return preg_replace_callback('/&([a-zA-Z][a-zA-Z0-9]+);/S', 276 | array($this, 'convert_entity'), $string); 277 | } 278 | 279 | /* Swap HTML named entity with its numeric equivalent. If the entity 280 | * isn't in the lookup table, this function returns a blank, which 281 | * destroys the character in the output - this is probably the 282 | * desired behaviour when producing XML. Adapted from code by @inanimatt: 283 | * https://gist.github.com/inanimatt/879249 284 | */ 285 | public function convert_entity($matches) { 286 | static $table = array( 287 | 'quot' => '"', 288 | 'amp' => '&', 289 | 'lt' => '<', 290 | 'gt' => '>', 291 | 'OElig' => 'Œ', 292 | 'oelig' => 'œ', 293 | 'Scaron' => 'Š', 294 | 'scaron' => 'š', 295 | 'Yuml' => 'Ÿ', 296 | 'circ' => 'ˆ', 297 | 'tilde' => '˜', 298 | 'ensp' => ' ', 299 | 'emsp' => ' ', 300 | 'thinsp' => ' ', 301 | 'zwnj' => '‌', 302 | 'zwj' => '‍', 303 | 'lrm' => '‎', 304 | 'rlm' => '‏', 305 | 'ndash' => '–', 306 | 'mdash' => '—', 307 | 'lsquo' => '‘', 308 | 'rsquo' => '’', 309 | 'sbquo' => '‚', 310 | 'ldquo' => '“', 311 | 'rdquo' => '”', 312 | 'bdquo' => '„', 313 | 'dagger' => '†', 314 | 'Dagger' => '‡', 315 | 'permil' => '‰', 316 | 'lsaquo' => '‹', 317 | 'rsaquo' => '›', 318 | 'euro' => '€', 319 | 'fnof' => 'ƒ', 320 | 'Alpha' => 'Α', 321 | 'Beta' => 'Β', 322 | 'Gamma' => 'Γ', 323 | 'Delta' => 'Δ', 324 | 'Epsilon' => 'Ε', 325 | 'Zeta' => 'Ζ', 326 | 'Eta' => 'Η', 327 | 'Theta' => 'Θ', 328 | 'Iota' => 'Ι', 329 | 'Kappa' => 'Κ', 330 | 'Lambda' => 'Λ', 331 | 'Mu' => 'Μ', 332 | 'Nu' => 'Ν', 333 | 'Xi' => 'Ξ', 334 | 'Omicron' => 'Ο', 335 | 'Pi' => 'Π', 336 | 'Rho' => 'Ρ', 337 | 'Sigma' => 'Σ', 338 | 'Tau' => 'Τ', 339 | 'Upsilon' => 'Υ', 340 | 'Phi' => 'Φ', 341 | 'Chi' => 'Χ', 342 | 'Psi' => 'Ψ', 343 | 'Omega' => 'Ω', 344 | 'alpha' => 'α', 345 | 'beta' => 'β', 346 | 'gamma' => 'γ', 347 | 'delta' => 'δ', 348 | 'epsilon' => 'ε', 349 | 'zeta' => 'ζ', 350 | 'eta' => 'η', 351 | 'theta' => 'θ', 352 | 'iota' => 'ι', 353 | 'kappa' => 'κ', 354 | 'lambda' => 'λ', 355 | 'mu' => 'μ', 356 | 'nu' => 'ν', 357 | 'xi' => 'ξ', 358 | 'omicron' => 'ο', 359 | 'pi' => 'π', 360 | 'rho' => 'ρ', 361 | 'sigmaf' => 'ς', 362 | 'sigma' => 'σ', 363 | 'tau' => 'τ', 364 | 'upsilon' => 'υ', 365 | 'phi' => 'φ', 366 | 'chi' => 'χ', 367 | 'psi' => 'ψ', 368 | 'omega' => 'ω', 369 | 'thetasym' => 'ϑ', 370 | 'upsih' => 'ϒ', 371 | 'piv' => 'ϖ', 372 | 'bull' => '•', 373 | 'hellip' => '…', 374 | 'prime' => '′', 375 | 'Prime' => '″', 376 | 'oline' => '‾', 377 | 'frasl' => '⁄', 378 | 'weierp' => '℘', 379 | 'image' => 'ℑ', 380 | 'real' => 'ℜ', 381 | 'trade' => '™', 382 | 'alefsym' => 'ℵ', 383 | 'larr' => '←', 384 | 'uarr' => '↑', 385 | 'rarr' => '→', 386 | 'darr' => '↓', 387 | 'harr' => '↔', 388 | 'crarr' => '↵', 389 | 'lArr' => '⇐', 390 | 'uArr' => '⇑', 391 | 'rArr' => '⇒', 392 | 'dArr' => '⇓', 393 | 'hArr' => '⇔', 394 | 'forall' => '∀', 395 | 'part' => '∂', 396 | 'exist' => '∃', 397 | 'empty' => '∅', 398 | 'nabla' => '∇', 399 | 'isin' => '∈', 400 | 'notin' => '∉', 401 | 'ni' => '∋', 402 | 'prod' => '∏', 403 | 'sum' => '∑', 404 | 'minus' => '−', 405 | 'lowast' => '∗', 406 | 'radic' => '√', 407 | 'prop' => '∝', 408 | 'infin' => '∞', 409 | 'ang' => '∠', 410 | 'and' => '∧', 411 | 'or' => '∨', 412 | 'cap' => '∩', 413 | 'cup' => '∪', 414 | 'int' => '∫', 415 | 'there4' => '∴', 416 | 'sim' => '∼', 417 | 'cong' => '≅', 418 | 'asymp' => '≈', 419 | 'ne' => '≠', 420 | 'equiv' => '≡', 421 | 'le' => '≤', 422 | 'ge' => '≥', 423 | 'sub' => '⊂', 424 | 'sup' => '⊃', 425 | 'nsub' => '⊄', 426 | 'sube' => '⊆', 427 | 'supe' => '⊇', 428 | 'oplus' => '⊕', 429 | 'otimes' => '⊗', 430 | 'perp' => '⊥', 431 | 'sdot' => '⋅', 432 | 'lceil' => '⌈', 433 | 'rceil' => '⌉', 434 | 'lfloor' => '⌊', 435 | 'rfloor' => '⌋', 436 | 'lang' => '〈', 437 | 'rang' => '〉', 438 | 'loz' => '◊', 439 | 'spades' => '♠', 440 | 'clubs' => '♣', 441 | 'hearts' => '♥', 442 | 'diams' => '♦', 443 | 'nbsp' => ' ', 444 | 'iexcl' => '¡', 445 | 'cent' => '¢', 446 | 'pound' => '£', 447 | 'curren' => '¤', 448 | 'yen' => '¥', 449 | 'brvbar' => '¦', 450 | 'sect' => '§', 451 | 'uml' => '¨', 452 | 'copy' => '©', 453 | 'ordf' => 'ª', 454 | 'laquo' => '«', 455 | 'not' => '¬', 456 | 'shy' => '­', 457 | 'reg' => '®', 458 | 'macr' => '¯', 459 | 'deg' => '°', 460 | 'plusmn' => '±', 461 | 'sup2' => '²', 462 | 'sup3' => '³', 463 | 'acute' => '´', 464 | 'micro' => 'µ', 465 | 'para' => '¶', 466 | 'middot' => '·', 467 | 'cedil' => '¸', 468 | 'sup1' => '¹', 469 | 'ordm' => 'º', 470 | 'raquo' => '»', 471 | 'frac14' => '¼', 472 | 'frac12' => '½', 473 | 'frac34' => '¾', 474 | 'iquest' => '¿', 475 | 'Agrave' => 'À', 476 | 'Aacute' => 'Á', 477 | 'Acirc' => 'Â', 478 | 'Atilde' => 'Ã', 479 | 'Auml' => 'Ä', 480 | 'Aring' => 'Å', 481 | 'AElig' => 'Æ', 482 | 'Ccedil' => 'Ç', 483 | 'Egrave' => 'È', 484 | 'Eacute' => 'É', 485 | 'Ecirc' => 'Ê', 486 | 'Euml' => 'Ë', 487 | 'Igrave' => 'Ì', 488 | 'Iacute' => 'Í', 489 | 'Icirc' => 'Î', 490 | 'Iuml' => 'Ï', 491 | 'ETH' => 'Ð', 492 | 'Ntilde' => 'Ñ', 493 | 'Ograve' => 'Ò', 494 | 'Oacute' => 'Ó', 495 | 'Ocirc' => 'Ô', 496 | 'Otilde' => 'Õ', 497 | 'Ouml' => 'Ö', 498 | 'times' => '×', 499 | 'Oslash' => 'Ø', 500 | 'Ugrave' => 'Ù', 501 | 'Uacute' => 'Ú', 502 | 'Ucirc' => 'Û', 503 | 'Uuml' => 'Ü', 504 | 'Yacute' => 'Ý', 505 | 'THORN' => 'Þ', 506 | 'szlig' => 'ß', 507 | 'agrave' => 'à', 508 | 'aacute' => 'á', 509 | 'acirc' => 'â', 510 | 'atilde' => 'ã', 511 | 'auml' => 'ä', 512 | 'aring' => 'å', 513 | 'aelig' => 'æ', 514 | 'ccedil' => 'ç', 515 | 'egrave' => 'è', 516 | 'eacute' => 'é', 517 | 'ecirc' => 'ê', 518 | 'euml' => 'ë', 519 | 'igrave' => 'ì', 520 | 'iacute' => 'í', 521 | 'icirc' => 'î', 522 | 'iuml' => 'ï', 523 | 'eth' => 'ð', 524 | 'ntilde' => 'ñ', 525 | 'ograve' => 'ò', 526 | 'oacute' => 'ó', 527 | 'ocirc' => 'ô', 528 | 'otilde' => 'õ', 529 | 'ouml' => 'ö', 530 | 'divide' => '÷', 531 | 'oslash' => 'ø', 532 | 'ugrave' => 'ù', 533 | 'uacute' => 'ú', 534 | 'ucirc' => 'û', 535 | 'uuml' => 'ü', 536 | 'yacute' => 'ý', 537 | 'thorn' => 'þ', 538 | 'yuml' => 'ÿ' 539 | ); 540 | // Entity not found? Destroy it. 541 | return isset($table[$matches[1]]) ? $table[$matches[1]] : ''; 542 | } /* FeedWordPie_Parser::convert_entity() */ 543 | 544 | } /* class FeedWordPie_Parser */ 545 | 546 | 547 | -------------------------------------------------------------------------------- /extend/SimplePie/SimplePie_Cache/feedwordpie_cache.class.php: -------------------------------------------------------------------------------- 1 | name = 'feed_' . $filename; 66 | $this->mod_name = 'feed_mod_' . $filename; 67 | 68 | $lifetime = $this->lifetime; 69 | /** 70 | * Filters the transient lifetime of the feed cache. 71 | * 72 | * @since 2.8.0 73 | * 74 | * @param int $lifetime Cache duration in seconds. Default is 43200 seconds (12 hours). 75 | * @param string $filename Unique identifier for the cache object. 76 | */ 77 | $this->lifetime = apply_filters( 'wp_feed_cache_transient_lifetime', $lifetime, $filename ); 78 | } 79 | 80 | /** 81 | * Sets the transient. 82 | * 83 | * @since 2.8.0 84 | * 85 | * @param SimplePie $data Data to save. 86 | * @return true Always true. 87 | */ 88 | public function save( $data ) { 89 | if ( $data instanceof SimplePie ) { 90 | $data = $data->data; 91 | } 92 | 93 | set_transient( $this->name, $data, $this->lifetime ); 94 | set_transient( $this->mod_name, time(), $this->lifetime ); 95 | return true; 96 | } 97 | 98 | /** 99 | * Gets the transient. 100 | * 101 | * @since 2.8.0 102 | * 103 | * @return mixed Transient value. 104 | */ 105 | public function load() { 106 | return get_transient( $this->name ); 107 | } 108 | 109 | /** 110 | * Gets mod transient. 111 | * 112 | * @since 2.8.0 113 | * 114 | * @return mixed Transient value. 115 | */ 116 | public function mtime() { 117 | return get_transient( $this->mod_name ); 118 | } 119 | 120 | /** 121 | * Sets mod transient. 122 | * 123 | * @since 2.8.0 124 | * 125 | * @return bool False if value was not set and true if value was set. 126 | */ 127 | public function touch() { 128 | return set_transient( $this->mod_name, time(), $this->lifetime ); 129 | } 130 | 131 | /** 132 | * Deletes transients. 133 | * 134 | * @since 2.8.0 135 | * 136 | * @return true Always true. 137 | */ 138 | public function unlink() { 139 | delete_transient( $this->name ); 140 | delete_transient( $this->mod_name ); 141 | return true; 142 | } 143 | 144 | /** 145 | * Create a new SimplePie_Cache object 146 | * 147 | * @param string $location URL location (scheme is used to determine handler) 148 | * @param string $filename Unique identifier for cache object 149 | * @param string $extension 'spi' or 'spc' 150 | * @return SimplePie_Cache_Base Type of object depends on scheme of `$location` 151 | */ 152 | public static function get_handler($location, $filename, $extension) 153 | { 154 | 155 | $type = explode(':', $location, 2); 156 | $type = $type[0]; 157 | if ( !empty(self::$handlers[$type])) 158 | { 159 | $class = self::$handlers[$type]; 160 | return $class($location, $filename, $extension); 161 | } 162 | 163 | return new FeedWordPie_Cache($location, $filename, $extension); 164 | } 165 | 166 | /** 167 | * Create a new SimplePie_Cache object 168 | * 169 | * @deprecated Use {@see get_handler} instead 170 | */ 171 | public function create($location, $filename, $extension) 172 | { 173 | trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED); 174 | return self::get_handler($location, $filename, $extension); 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /extend/SimplePie/default/feedwordpie_cache.class.php: -------------------------------------------------------------------------------- 1 | name = 'feed_' . $filename; 66 | $this->mod_name = 'feed_mod_' . $filename; 67 | 68 | $lifetime = $this->lifetime; 69 | /** 70 | * Filters the transient lifetime of the feed cache. 71 | * 72 | * @since 2.8.0 73 | * 74 | * @param int $lifetime Cache duration in seconds. Default is 43200 seconds (12 hours). 75 | * @param string $filename Unique identifier for the cache object. 76 | */ 77 | $this->lifetime = apply_filters( 'wp_feed_cache_transient_lifetime', $lifetime, $filename ); 78 | } 79 | 80 | /** 81 | * Sets the transient. 82 | * 83 | * @since 2.8.0 84 | * 85 | * @param SimplePie $data Data to save. 86 | * @return true Always true. 87 | */ 88 | public function save( $data ) { 89 | if ( $data instanceof SimplePie ) { 90 | $data = $data->data; 91 | } 92 | 93 | set_transient( $this->name, $data, $this->lifetime ); 94 | set_transient( $this->mod_name, time(), $this->lifetime ); 95 | return true; 96 | } 97 | 98 | /** 99 | * Gets the transient. 100 | * 101 | * @since 2.8.0 102 | * 103 | * @return mixed Transient value. 104 | */ 105 | public function load() { 106 | return get_transient( $this->name ); 107 | } 108 | 109 | /** 110 | * Gets mod transient. 111 | * 112 | * @since 2.8.0 113 | * 114 | * @return mixed Transient value. 115 | */ 116 | public function mtime() { 117 | return get_transient( $this->mod_name ); 118 | } 119 | 120 | /** 121 | * Sets mod transient. 122 | * 123 | * @since 2.8.0 124 | * 125 | * @return bool False if value was not set and true if value was set. 126 | */ 127 | public function touch() { 128 | return set_transient( $this->mod_name, time(), $this->lifetime ); 129 | } 130 | 131 | /** 132 | * Deletes transients. 133 | * 134 | * @since 2.8.0 135 | * 136 | * @return true Always true. 137 | */ 138 | public function unlink() { 139 | delete_transient( $this->name ); 140 | delete_transient( $this->mod_name ); 141 | return true; 142 | } 143 | 144 | /** 145 | * Create a new SimplePie_Cache object 146 | * 147 | * @param string $location URL location (scheme is used to determine handler) 148 | * @param string $filename Unique identifier for cache object 149 | * @param string $extension 'spi' or 'spc' 150 | * @return SimplePie_Cache_Base Type of object depends on scheme of `$location` 151 | */ 152 | public static function get_handler($location, $filename, $extension) 153 | { 154 | 155 | $type = explode(':', $location, 2); 156 | $type = $type[0]; 157 | if ( !empty(self::$handlers[$type])) 158 | { 159 | $class = self::$handlers[$type]; 160 | return $class($location, $filename, $extension); 161 | } 162 | 163 | return new FeedWordPie_Cache($location, $filename, $extension); 164 | } 165 | 166 | /** 167 | * Create a new SimplePie_Cache object 168 | * 169 | * @deprecated Use {@see get_handler} instead 170 | */ 171 | public function create($location, $filename, $extension) 172 | { 173 | trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED); 174 | return self::get_handler($location, $filename, $extension); 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /extend/SimplePie/default/feedwordpie_item.class.php: -------------------------------------------------------------------------------- 1 | uri(array('add_params' => true, 'fetch' => true)); 14 | 15 | // Store for reference. 16 | $this->subscription = $url->id(); 17 | 18 | // Pass it along down the line. 19 | $url = $new_url; 20 | 21 | else : 22 | $this->subscription = NULL; 23 | endif; 24 | 25 | // OK, let's go. 26 | return parent::set_feed_url($url); 27 | } /* class SimplePie */ 28 | 29 | function get_type () { 30 | // Allow filters to pre-empt a type determination from SimplePie 31 | $ret = apply_filters( 32 | 'feedwordpie_get_type', 33 | NULL, 34 | $this 35 | ); 36 | 37 | // If not preempted by a filter, fall back on SimplePie 38 | if (is_null($ret)) : 39 | $ret = parent::get_type(); 40 | endif; 41 | 42 | return $ret; 43 | } 44 | 45 | function get_feed_tags ($namespace, $tag) { 46 | $tags = parent::get_feed_tags($namespace, $tag); 47 | 48 | // Allow filters to filter SimplePie handling 49 | return apply_filters( 50 | 'feedwordpie_get_feed_tags', 51 | $tags, 52 | $namespace, 53 | $tag, 54 | $this 55 | ); 56 | } 57 | 58 | function get_items ($start = 0, $end = 0) { 59 | // Allow filters to set up for, or pre-empt, SimplePie handling 60 | $ret = apply_filters( 61 | 'feedwordpie_get_items', 62 | NULL, 63 | $start, 64 | $end, 65 | $this 66 | ); 67 | 68 | if (is_null($ret)) : 69 | $ret = parent::get_items(); 70 | endif; 71 | return $ret; 72 | } 73 | 74 | } /* class FeedWordPie */ 75 | 76 | -------------------------------------------------------------------------------- /extend/SimplePie/feedwordpie_cache.class.php: -------------------------------------------------------------------------------- 1 | file->headers['content-type'])) : 17 | if ( !is_array($this->file->headers['content-type'])) : 18 | $this->file->headers['content-type'] = array($this->file->headers['content-type']); 19 | endif; 20 | 21 | foreach ($this->file->headers['content-type'] as $type) : 22 | $parts = array_map('trim', explode(";", $type, 2)); 23 | if (isset($parts[1])) : 24 | $type = $parts[0]; 25 | $charset = $parts[1]; 26 | endif; 27 | 28 | if (preg_match( 29 | '!(application|text)/((atom|rss|rdf)\+)?xml!', 30 | $type, 31 | $ref 32 | )) : 33 | $contentType = $ref[0]; 34 | endif; 35 | endforeach; 36 | 37 | $outHeader = array(); 38 | if ( !is_null($contentType)) : 39 | $outHeader[] = $contentType; 40 | else : 41 | $outHeader[] = 'text/xml'; // Generic 42 | endif; 43 | if ( !is_null($charset)) : 44 | $outHeader[] = $charset; 45 | endif; 46 | 47 | $this->file->headers['content-type'] = implode("; ", $outHeader); 48 | else : 49 | // The default SimplePie behavior seems to be to return 50 | // text/plain if it can't find a Content-Type header. 51 | // The default SimplePie behavior sucks. Particularly 52 | // since SimplePie gets so draconian about Content-Type. 53 | // And since the WP SimplePie seems to drop Content-Type 54 | // from cached copies for some unfortunate reason. 55 | $this->file->headers['content-type'] = 'text/xml'; // Generic 56 | endif; 57 | return parent::get_type(); 58 | } /* FeedWordPie_Content_Type_Sniffer::get_type() */ 59 | } /* class FeedWordPie_Content_Type_Sniffer */ 60 | 61 | -------------------------------------------------------------------------------- /extend/SimplePie/feedwordpie_file.class.php: -------------------------------------------------------------------------------- 1 | subscribed( $url ) ) : 48 | $source = $feedwordpress->subscription( $url ); 49 | endif; 50 | 51 | $this->url = $url; 52 | $this->timeout = $timeout; 53 | $this->redirects = $redirects; 54 | $this->headers = $headers; 55 | $this->useragent = $useragent; 56 | 57 | $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE; 58 | 59 | global $fwp_credentials; 60 | 61 | if ( preg_match( '/^http(s)?:\/\//i', $url ) ) : 62 | $args = array( 'timeout' => $this->timeout, 'redirection' => $this->redirects ); 63 | 64 | if ( ! empty( $this->headers ) ) : 65 | $args['headers'] = $this->headers; 66 | endif; 67 | 68 | // Use default FWP user agent unless custom has been specified 69 | if ( SIMPLEPIE_USERAGENT != $this->useragent ) : 70 | $args['user-agent'] = $this->useragent; 71 | else : 72 | $args['user-agent'] = apply_filters( 73 | 'feedwordpress_user_agent', 74 | 'FeedWordPress/' . FEEDWORDPRESS_VERSION 75 | . ' (aggregator:feedwordpress; WordPress/' . $wp_version 76 | . ' + ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION 77 | . '; Allow like Gecko; +http://feedwordpress.radgeek.com/) at ' 78 | . feedwordpress_display_url( get_bloginfo( 'url' ) ), 79 | $this 80 | ); 81 | endif; 82 | 83 | // This is ugly as hell, but communicating up and down the chain 84 | // in any other way is difficult. 85 | if ( ! is_null( $fwp_credentials ) ) : 86 | $args['authentication'] = $fwp_credentials['authentication']; 87 | $args['username'] = $fwp_credentials['username']; 88 | $args['password'] = $fwp_credentials['password']; 89 | elseif ( $source InstanceOf SyndicatedLink ) : 90 | $args['authentication'] = $source->authentication_method(); 91 | $args['username'] = $source->username(); 92 | $args['password'] = $source->password(); 93 | endif; 94 | 95 | FeedWordPress::diagnostic( 'updated_feeds:http', "HTTP [$url] ⌈ " . esc_html( MyPHP::val( $args ) ) ); 96 | $res = wp_remote_request( $url, $args ); 97 | FeedWordPress::diagnostic( 'updated_feeds:http', "HTTP [$url] ⌉ " . esc_html( MyPHP::val( $res ) ) ); 98 | 99 | if ( is_wp_error( $res ) ) : 100 | $this->error = 'WP HTTP Error: ' . $res->get_error_message(); 101 | $this->success = false; 102 | else : 103 | $this->headers = wp_remote_retrieve_headers( $res ); 104 | $this->body = wp_remote_retrieve_body( $res ); 105 | $this->status_code = wp_remote_retrieve_response_code( $res ); 106 | endif; 107 | 108 | if ( $source InstanceOf SyndicatedLink ) : 109 | $source->update_setting( 'link/filesize', strlen( $this->body ) ); 110 | $source->update_setting( 'link/http status', $this->status_code ); 111 | $source->save_settings( /*reload=*/ true ); 112 | endif; 113 | 114 | /* Do not allow schemes other than http(s)? for the time being. 115 | * They are unlikely to be used; and unrestricted use of schemes 116 | * allows for user to use an unrestricted file:/// scheme, which 117 | * may result in exploits by WordPress users against the web 118 | * hosting environment. 119 | */ 120 | else : 121 | $this->error = __( 'FeedWordPress only allows HTTP or HTTPS URL schemes' ); 122 | $this->success = false; 123 | endif; 124 | 125 | /* SimplePie makes a strongly typed check against integers with 126 | * this, but WordPress puts a string in. Which causes caching 127 | * to break and fall on its ass when SimplePie is getting a 304, 128 | * but doesn't realize it because this member is "304" instead. 129 | */ 130 | $this->status_code = (int) $this->status_code; 131 | } /* FeedWordPie_File::__construct () */ 132 | } /* class FeedWordPie_File () */ 133 | 134 | -------------------------------------------------------------------------------- /extend/SimplePie/feedwordpie_item.class.php: -------------------------------------------------------------------------------- 1 | ) 36 | // Happily they were DEPRECATED as of PHP 5.3.0, 37 | // and REMOVED as of PHP 5.4.0, so we don't need 38 | // to worry about them anymore. 39 | endif; 40 | endif; 41 | 42 | return $ret; 43 | } /* MyPHP::param() */ 44 | 45 | /** 46 | * MyPHP::post: For dealing with HTTP POST parameters sent as input 47 | * 48 | * @param string $key The name of the POST parameter 49 | * @param mixed $default Default to return if parameter is unset 50 | * @return mixed The value of the named parameter, or the fallback 51 | * in $default if there is no value set for that param name. 52 | */ 53 | static function post( $key, $default = NULL ) { 54 | return self::param( $key, $default, 'POST' ); 55 | } /* MyPHP::post() */ 56 | 57 | /** 58 | * MyPHP::post: For dealing with HTTP GET parameters sent as input 59 | * 60 | * @param string $key The name of the GET parameter 61 | * @param mixed $default Default to return if parameter is unset 62 | * @return mixed The value of the named parameter, or the fallback 63 | * in $default if there is no value set for that param name. 64 | */ 65 | static function get( $key, $default = NULL ) { 66 | return self::param( $key, $default, "GET" ); 67 | } /* MyPHP::get() */ 68 | 69 | /** 70 | * MyPHP::request: For dealing with HTTP GET/POST parameters 71 | * sent as input. This method checks both GET parameters and POST 72 | * parameters and will return values from either. 73 | * 74 | * @param string $key The name of the GET/POST parameter 75 | * @param mixed $default Default to return if parameter is unset 76 | * @return mixed The value of the named parameter, or the fallback 77 | * in $default if there is no value set for that param name. 78 | */ 79 | static function request( $key, $default = NULL ) { 80 | return self::param( $key, $default, "REQUEST" ); 81 | } /* MyPHP::request () */ 82 | 83 | /** 84 | * MyPHP::request: Makes sure that we strip all slashes and double slashes 85 | * we happen to encounter on our strings. 86 | * 87 | * The function is recursive and gets as deep as it must. 88 | * 89 | * @param array|object|string $value Item to de-slash. 90 | * 91 | * @return array|object|string De-slashed item. 92 | */ 93 | static function stripslashes_deep( $value ) { 94 | if ( is_array( $value ) ) { 95 | $value = array_map( array( __CLASS__, 'stripslashes_deep' ), $value ); 96 | } elseif ( is_object( $value ) ) { 97 | $vars = get_object_vars( $value ); 98 | foreach ( $vars as $key => $data ) { 99 | $value->{$key} = stripslashes_deep( $data ); 100 | } 101 | } else { 102 | $value = stripslashes( $value ); 103 | } 104 | return $value; 105 | } /* MyPHP::stripslashes_deep () */ 106 | 107 | /** 108 | * Constructs an URL with the list of passed parameters. 109 | * 110 | * @param string $url Base URL. 111 | * @param Array $params Variable parameters. 112 | * 113 | * @return string 114 | */ 115 | static function url( $url, $params = array() ) { 116 | $sep = '?'; 117 | if ( strpos( $url, '?' ) !== false ) : 118 | $sep = '&'; 119 | endif; 120 | $url .= $sep . self::to_http_post( $params ); 121 | 122 | return $url; 123 | } /* MyPHP::url () */ 124 | 125 | /** 126 | * MyPHP::to_http_post () -- convert a hash table or object into 127 | * an application/x-www-form-urlencoded query string 128 | * 129 | * @param mixed $params Hash table/object to convert. 130 | * 131 | * @return string The application/x-www-form-urlencoded query string. 132 | */ 133 | static function to_http_post( $params ) { 134 | $getQuery = array(); 135 | foreach ( $params as $key => $value ) : 136 | if ( is_scalar( $value ) ) : 137 | $getQuery[] = urlencode( $key ) . '=' . urlencode( $value ); 138 | else : 139 | // Make some attempt to deal with array and 140 | // object members. Really we should descend 141 | // recursively to get the whole thing.... 142 | foreach ((array) $value as $k => $v ) : 143 | $getQuery[] = urlencode( $key . '[' . $k . ']' ) . '=' . urlencode( $v ); 144 | endforeach; 145 | endif; 146 | endforeach; 147 | return implode( "&", $getQuery ); 148 | } /* MyPHP::to_http_post () */ 149 | 150 | /** 151 | * MyPHP::val(): Captures the output of var_dump() to a string, 152 | * with some optional filtering removing newlines and replacing 153 | * them with spaces) applied. 154 | * 155 | * @note As far as _I_ understand regexes, this replaces _multiple_ 156 | * consecutive whitespace elements with a single space — which is 157 | * not quite what the description says! However, since the result of 158 | * var_dump() has a reasonably predictable output, so this _may_ work 159 | * as intended...(gwyneth 20230916) 160 | * 161 | * @param mixed $v Value to dump to a string representation. 162 | * @param bool $no_newlines Whether to filter out newline chars. 163 | * 164 | * @return string Captured & cleaned-up output of var_dump(). 165 | */ 166 | static function val( $v, $no_newlines = false ) { 167 | ob_start(); 168 | var_dump( $v ); 169 | $out = ob_get_contents(); ob_end_clean(); 170 | if ( $no_newlines ) : 171 | $out = preg_replace( '/\s+/', " ", $out ); 172 | endif; 173 | return $out; 174 | } /* MyPHP::val () */ 175 | } /* class MyPHP */ 176 | endif; 177 | -------------------------------------------------------------------------------- /feedfinder.class.php: -------------------------------------------------------------------------------- 1 | $params); 48 | endif; 49 | 50 | $params = wp_parse_args($params, array( 51 | "verify" => true, 52 | "authentication" => NULL, 53 | "username" => NULL, 54 | "password" => NULL, 55 | )); 56 | $verify = $params['verify']; 57 | $this->credentials = array( 58 | "authentication" => $params['authentication'], 59 | "username" => $params['username'], 60 | "password" => $params['password'], 61 | ); 62 | 63 | $this->uri = $uri; $this->verify = $verify; 64 | $this->fallbacks = $fallbacks; 65 | } /* FeedFinder::FeedFinder () */ 66 | 67 | function FeedFinder( $uri = NULL, $params = array(), $fallbacks = 3 ) { 68 | self::__construct( $uri, $params, $fallbacks ); 69 | } 70 | 71 | function find ($uri = NULL, $params = array()) { 72 | $params = wp_parse_args($params, array( // Defaults 73 | "authentication" => -1, 74 | "username" => NULL, 75 | "password" => NULL, 76 | )); 77 | 78 | // Equivalents 79 | if ($params['authentication']=='-') : 80 | $params['authentication'] = NULL; 81 | $params['username'] = NULL; 82 | $params['password'] = NULL; 83 | endif; 84 | 85 | // Set/reset 86 | if ($params['authentication'] != -1) : 87 | $this->credentials = array( 88 | "authentication" => $params['authentication'], 89 | "username" => $params['username'], 90 | "password" => $params['password'], 91 | ); 92 | endif; 93 | 94 | $ret = array (); 95 | if ( !is_null($this->data($uri))) : 96 | if ($this->is_opml($uri)) : 97 | $href = $this->_opml_rss_uris(); 98 | else : 99 | if ($this->is_feed($uri)) : 100 | $href = array($this->uri); 101 | else : 102 | // Assume that we have HTML or XHTML (even if we don't, who's 103 | // it gonna hurt?) Autodiscovery is the preferred method. 104 | $href = $this->_link_rel_feeds(); 105 | 106 | // ... but we'll also take the little orange buttons 107 | if ($this->fallbacks > 0) : 108 | $href = array_merge($href, $this->_a_href_feeds(TRUE)); 109 | endif; 110 | 111 | // If all that failed, look harder 112 | if ($this->fallbacks > 1) : 113 | if (count($href) == 0) : 114 | $href = $this->_a_href_feeds(FALSE); 115 | endif; 116 | endif; 117 | 118 | // Our search may turn up duplicate URIs. We only need to do 119 | // any given URI once. Props to Camilo 120 | $href = array_unique($href); 121 | endif; 122 | 123 | // Try some clever URL little tricks before we go 124 | if ($this->fallbacks > 2) : 125 | $href = array_merge($href, $this->_url_manipulation_feeds()); 126 | endif; 127 | endif; 128 | 129 | $href = array_unique($href); 130 | 131 | // Verify feeds and resolve relative URIs 132 | foreach ($href as $u) : 133 | $the_uri = SimplePie_Misc::absolutize_url($u, $this->uri); 134 | if ($this->verify and ($u != $this->uri and $the_uri != $this->uri)) : 135 | $feed = new FeedFinder($the_uri, $this->credentials); 136 | if ($feed->is_feed()) : $ret[] = $the_uri; endif; 137 | unset($feed); 138 | else : 139 | $ret[] = $the_uri; 140 | endif; 141 | endforeach; 142 | endif; 143 | 144 | if ($this->is_401($uri)) : 145 | $ret = array_merge(array( 146 | new WP_Error('http_request_failed', '401 Not authorized', array("uri" => $this->uri, "status" => 401)), 147 | ), $ret); 148 | endif; 149 | 150 | return array_values($ret); 151 | } /* FeedFinder::find () */ 152 | 153 | function data ($uri = NULL) { 154 | $this->_get($uri); 155 | return $this->_data; 156 | } /* FeedFinder::data () */ 157 | 158 | function upload_data ($data) { 159 | $this->uri = 'tag:localhost'; 160 | $this->_data = $data; 161 | } /* FeedFinder::upload_data () */ 162 | 163 | function status ($uri = NULL) { 164 | $this->_get($uri); 165 | 166 | if ( !is_wp_error($this->_response) and isset($this->_response['response']['code'])) : 167 | $ret = $this->_response['response']['code']; 168 | else : 169 | $ret = NULL; 170 | endif; 171 | return $ret; 172 | } 173 | 174 | function error ($index = NULL) { 175 | $message = NULL; 176 | if (count($this->_error) > 0) : 177 | if (is_scalar($index) and !is_null($index)) : 178 | $message = $this->_error[$index]; 179 | else : 180 | $message = implode(" / ", $this->_error)."\n"; 181 | endif; 182 | endif; 183 | return $message; 184 | } 185 | 186 | function is_401 ($uri = NULL) { 187 | return (intval($this->status($uri))==401); 188 | } /* FeedFinder::is_401 () */ 189 | 190 | function is_feed ($uri = NULL) { 191 | $data = $this->data($uri); 192 | 193 | return ( 194 | preg_match ( 195 | "\007(".implode('|',$this->_feed_markers).")\007i", 196 | $data 197 | ) and !preg_match ( 198 | "\007(".implode('|',$this->_html_markers).")\007i", 199 | $data 200 | ) 201 | ); 202 | } /* FeedFinder::is_feed () */ 203 | 204 | function is_opml ($uri = NULL) { 205 | $data = $this->data($uri); 206 | return ( 207 | preg_match ( 208 | "\007(".implode('|',$this->_opml_markers).")\007i", 209 | $data 210 | ) 211 | ); 212 | } /* FeedFinder::is_opml () */ 213 | 214 | # --- Private methods --- 215 | function _get ($uri = NULL) { 216 | if ($uri) $this->uri = $uri; 217 | 218 | // Is the result not yet cached? 219 | if ($this->uri != 'tag:localhost' and $this->_cache_uri !== $this->uri) : 220 | $headers['Connection'] = 'close'; 221 | $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*'; 222 | $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress'; 223 | 224 | // Use WordPress API function 225 | $client = wp_remote_request($this->uri, array_merge( 226 | $this->credentials, 227 | array( 228 | 'headers' => $headers, 229 | 'timeout' => FeedWordPress::fetch_timeout(), 230 | ) 231 | )); 232 | 233 | $this->_response = $client; 234 | if (is_wp_error($client)) : 235 | $this->_data = NULL; 236 | $this->_error = $client->get_error_messages(); 237 | else : 238 | $this->_data = $client['body']; 239 | $this->_error = NULL; 240 | endif; 241 | 242 | // Kilroy was here 243 | $this->_cache_uri = $this->uri; 244 | endif; 245 | } /* FeedFinder::_get () */ 246 | 247 | function _opml_rss_uris () { 248 | // Really we should parse the XML and use the structure to 249 | // return something intelligent to programs that want to use it 250 | // Oh babe! maybe some day... 251 | 252 | $opml = $this->data(); 253 | 254 | $rx = FeedWordPressHTML::attributeRegex('outline', 'xmlUrl'); 255 | if (preg_match_all($rx, $opml, $matches, PREG_SET_ORDER)) : 256 | foreach ($matches as $m) : 257 | $match = FeedWordPressHTML::attributeMatch($m); 258 | $r[] = $match['value']; 259 | endforeach; 260 | endif; 261 | return $r; 262 | } /* FeedFinder::_opml_rss_uris () */ 263 | 264 | function _link_rel_feeds () { 265 | $links = $this->_tags('link'); 266 | $link_count = count($links); 267 | 268 | // now figure out which one points to the RSS file 269 | $href = array (); 270 | for ($n=0; $n<$link_count; $n++) { 271 | if (strtolower($links[$n]['rel']) == 'alternate') { 272 | if (in_array(strtolower($links[$n]['type']), $this->_feed_types)) { 273 | $href[] = $links[$n]['href']; 274 | } /* if */ 275 | } /* if */ 276 | } /* for */ 277 | return $href; 278 | } /* FeedFinder::_link_rel_feeds () */ 279 | 280 | function _a_href_feeds ($obvious = TRUE) { 281 | $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url); 282 | 283 | $links = $this->_tags('a'); 284 | $link_count = count($links); 285 | 286 | // now figure out which one points to the RSS file 287 | $href = array (); 288 | for ($n=0; $n<$link_count; $n++) { 289 | if (preg_match("\007(".implode('|',$pattern).")\007i", $links[$n]['href'])) { 290 | $href[] = $links[$n]['href']; 291 | } /* if */ 292 | } /* for */ 293 | return $href; 294 | } /* FeedFinder::_link_a_href_feeds () */ 295 | 296 | function _url_manipulation_feeds () { 297 | $href = array(); 298 | 299 | // check for HTTP GET parameters that look feed-like. 300 | $bits = parse_url($this->uri); 301 | foreach (array('rss', 'rss2', 'atom', 'rdf') as $format) : 302 | if (isset($bits['query']) and (strlen($bits['query']) > 0)) : 303 | $newQuery = preg_replace('/([?&=])(rss2?|atom|rdf)/i', '$1'.$format, $bits['query']); 304 | else : 305 | $newQuery = NULL; 306 | endif; 307 | 308 | if (isset($bits['path']) and (strlen($bits['path']) > 0)) : 309 | $newPath = preg_replace('!([/.])(rss2?|atom|rdf)!i', '$1'.$format, $bits['path']); 310 | else : 311 | $newPath = NULL; 312 | endif; 313 | 314 | // Reassemble, check and return 315 | $credentials = ''; 316 | if (isset($bits['user'])) : 317 | $credentials = $bits['user']; 318 | if (isset($bits['pass'])) : 319 | $credentials .= ':'.$bits['pass']; 320 | endif; 321 | $credentials .= '@'; 322 | endif; 323 | 324 | // Variations on a theme 325 | $newUrl[0] = ('' 326 | .(isset($bits['scheme']) ? $bits['scheme'].':' : '') 327 | .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '') 328 | .( !is_null($newPath) ? $newPath : '') 329 | .( !is_null($newQuery) ? '?'.$newQuery : '') 330 | .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '') 331 | ); 332 | $newUrl[1] = ('' 333 | .(isset($bits['scheme']) ? $bits['scheme'].':' : '') 334 | .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '') 335 | .( !is_null($newPath) ? $newPath : '') 336 | .(isset($bits['query']) ? '?'.$bits['query'] : '') 337 | .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '') 338 | ); 339 | $newUrl[2] = ('' 340 | .(isset($bits['scheme']) ? $bits['scheme'].':' : '') 341 | .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '') 342 | .(isset($bits['path']) ? $bits['path'] : '') 343 | .( !is_null($newQuery) ? '?'.$newQuery : '') 344 | .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '') 345 | ); 346 | $href = array_merge($href, $newUrl); 347 | endforeach; 348 | return array_unique($href); 349 | } /* FeedFinder::_url_manipulation_feeds () */ 350 | 351 | function _tags ($tag) { 352 | $html = $this->data(); 353 | 354 | // search through the HTML, save all tags 355 | // and store each link's attributes in an associative array 356 | preg_match_all('/<'.$tag.'\s+(.*?)\s*\/?>/si', $html, $matches); 357 | $links = $matches[1]; 358 | $ret = array(); 359 | $link_count = count($links); 360 | for ($n=0; $n<$link_count; $n++) { 361 | $attributes = preg_split('/\s+/s', $links[$n]); 362 | foreach($attributes as $attribute) { 363 | $att = preg_split('/\s*=\s*/s', $attribute, 2); 364 | if (isset($att[1])) { 365 | $att[1] = preg_replace('/([\'"]?)(.*)\1/', '$2', $att[1]); 366 | $final_link[strtolower($att[0])] = $att[1]; 367 | } /* if */ 368 | } /* foreach */ 369 | $ret[$n] = $final_link; 370 | } /* for */ 371 | return $ret; 372 | } /* FeedFinder::_tags () */ 373 | } /* class FeedFinder */ 374 | 375 | -------------------------------------------------------------------------------- /feedtime.class.php: -------------------------------------------------------------------------------- 1 | failed()) : 18 | * $ts = $time->timestamp(); 19 | * else : 20 | * // ... 21 | * endif; 22 | */ 23 | class FeedTime { 24 | var $rep; 25 | var $ts; 26 | 27 | function __construct( $time ) { 28 | $this->set($time); 29 | } /* FeedTime constructor */ 30 | 31 | function FeedTime( $time ) { 32 | self::__construct( $time ); 33 | } 34 | 35 | function set ($time, $recurse = false) { 36 | $this->rep = $time; 37 | $this->ts = NULL; 38 | if (is_numeric($time)) : // Presumably a Unix-epoch timestamp 39 | $this->ts = $this->rep; 40 | elseif (is_string($time)) : 41 | // First, try to parse it as a W3C date-time 42 | $this->ts = $this->parse_w3cdtf(); 43 | 44 | if ($this->failed()) : 45 | // In some versions of PHP, strtotime() does not 46 | // support the UT timezone. But since UT is by 47 | // definition within 1 second of UTC, we'll just 48 | // convert it preemptively to avoid problems. 49 | $time = preg_replace( 50 | '/(\s)UT$/', 51 | '$1UTC', 52 | $time 53 | ); 54 | $this->ts = strtotime($time); 55 | 56 | if ($this->failed() 57 | and preg_match('/^(.*)([+\-][0-9]+|\s+[A-Za-z]{1,3})$/', $time, $matches)) : 58 | // Try dropping the time zone and recurse 59 | $this->set($matches[1], /*recurse=*/ true); 60 | endif; 61 | endif; 62 | endif; 63 | } /* FeedTime::set() */ 64 | 65 | function timestamp () { 66 | $unix = NULL; 67 | if ( ! $this->failed()) : 68 | $unix = $this->ts; 69 | endif; 70 | return $unix; 71 | } /* FeedTime::timestamp() */ 72 | 73 | function failed () { 74 | return ( !is_numeric($this->ts) or ! $this->ts or ($this->ts <= 0)); 75 | } /* FeedTime::failed() */ 76 | 77 | /** 78 | * FeedTime::parse_w3cdtf() parses a W3C date-time format date into a 79 | * Unix epoch timestamp. Derived from the parse_w3cdtf function included 80 | * with MagpieRSS by Kellan Elliot-McCrea , with 81 | * modifications and bugfixes by Charles Johnson 82 | * , under the terms of the GPL. 83 | */ 84 | function parse_w3cdtf () { 85 | $unix = NULL; // Failure 86 | 87 | # regex to match wc3dtf 88 | $pat = "/^\s* 89 | (\d{4}) 90 | (- 91 | (\d{2}) 92 | (- 93 | (\d{2}) 94 | (T 95 | (\d{2}) 96 | :(\d{2}) 97 | (: 98 | (\d{2}) 99 | (\.\d+)? 100 | )? 101 | (?:([-+])(\d{2}):?(\d{2})|(Z))? 102 | )? 103 | )? 104 | )? 105 | \s*\$ 106 | /x"; 107 | 108 | if ( preg_match( $pat, $this->rep, $match ) ) : 109 | $year = (isset($match[1]) ? $match[1] : NULL); 110 | $month = (isset($match[3]) ? $match[3] : NULL); 111 | $day = (isset($match[5]) ? $match[5] : NULL); 112 | $hours = (isset($match[7]) ? $match[7] : NULL); 113 | $minutes = (isset($match[8]) ? $match[8] : NULL); 114 | $seconds = (isset($match[10]) ? $match[10] : NULL); 115 | 116 | # W3C dates can omit the time, the day of the month, or even the month. 117 | # Fill in any blanks using information from the present moment. --CWJ 118 | $default['hr'] = (int) gmdate('H'); 119 | $default['day'] = (int) gmdate('d'); 120 | $default['month'] = (int) gmdate('m'); 121 | 122 | if (is_null($hours)) : $hours = $default['hr']; $minutes = 0; $seconds = 0; endif; 123 | if (is_null($day)) : $day = $default['day']; endif; 124 | if (is_null($month)) : $month = $default['month']; endif; 125 | 126 | # calc epoch for current date assuming GMT 127 | $unix = gmmktime( $hours, $minutes, $seconds, $month, $day, $year); 128 | 129 | $offset = 0; 130 | if ( isset($match[15]) and $match[15] == 'Z' ) : 131 | # zulu time, aka GMT 132 | else : 133 | $tz_mod = (isset($match[12]) ? $match[12] : NULL); 134 | $tz_hour = (isset($match[13]) ? $match[13] : NULL); 135 | $tz_min = (isset($match[14]) ? $match[14] : NULL); 136 | 137 | # zero out the variables 138 | if ( is_null($tz_hour) ) : 139 | $offset = (int) get_option('gmt_offset'); 140 | $tz_hour = abs($offset); 141 | $tz_mod = ((abs($offset) != $offset) ? '-' : '+'); 142 | endif; 143 | if ( is_null($tz_min) ) : $tz_min = 0; endif; 144 | 145 | $offset_secs = (($tz_hour*60)+$tz_min)*60; 146 | 147 | # is timezone ahead of GMT? then subtract offset 148 | if ( $tz_mod == '+' ) : 149 | $offset_secs = $offset_secs * -1; 150 | endif; 151 | $offset = $offset_secs; 152 | endif; 153 | $unix = $unix + $offset; 154 | endif; 155 | return $unix; 156 | } /* FeedTime::parse_w3cdtf () */ 157 | } /* class FeedTime */ 158 | -------------------------------------------------------------------------------- /feedwordpress-walker-category-checklist.class.php: -------------------------------------------------------------------------------- 1 | set_taxonomy('category'); 18 | 19 | if (isset($params['checkbox_name'])) : 20 | $this->checkbox_name = $params['checkbox_name']; 21 | endif; 22 | } /* FeedWordPress_Walker_Category_Checklist::__construct () */ 23 | 24 | function set_prefix ($prefix) { 25 | $this->prefix = $prefix; 26 | } 27 | function set_taxonomy ($taxonomy) { 28 | $this->taxonomy = $taxonomy; 29 | } 30 | 31 | function start_el (&$output, $category, $depth = 0, $args = array(), $id = 0) { 32 | extract($args); 33 | if ( empty($taxonomy) ) : 34 | $taxonomy = 'category'; 35 | endif; 36 | 37 | if ( !is_null($this->checkbox_name)) : 38 | $name = $this->checkbox_name; 39 | elseif ($taxonomy=='category') : 40 | $name = 'post_category'; 41 | else : 42 | $name = 'tax_input['.$taxonomy.']'; 43 | endif; 44 | 45 | $unit = array(); 46 | if (strlen($this->prefix) > 0) : 47 | $unit[] = $this->prefix; 48 | endif; 49 | $unit[] = $taxonomy; 50 | $unit[] = $category->term_id; 51 | $unitId = implode("-", $unit); 52 | 53 | $class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category category-checkbox"' : ' class="category-checkbox"'; 54 | $output .= "\n
  • " . ''; 55 | } /* FeedWordPress_Walker_Category_Checklist::start_el() */ 56 | } /* FeedWordPress_Walker_Category_Checklist */ 57 | -------------------------------------------------------------------------------- /feedwordpress.pings.functions.php: -------------------------------------------------------------------------------- 1 | ID ); 61 | $frozen_post = ( null !== $frozen_values and count( $frozen_values ) > 0 and 'yes' == $frozen_values[0] ); 62 | 63 | if ( ! empty( $post ) and ! empty( $post->ID ) and is_syndicated( $post->ID ) ) : 64 | ?> 65 |

    66 | ID ) ); ?>. 67 | .

    68 | 69 | 70 | 71 |

    72 |

    74 | 75 | 76 | 77 | 80 |

    81 | ID ) : 112 | return $post_id; 113 | endif; 114 | 115 | // Check permissions 116 | $cap[0] = 'edit_post'; 117 | 118 | $post_type = FeedWordPress::post( 'post_type' ); 119 | $cap[1] = sanitize_key( 'edit_' . $post_type ); 120 | 121 | if ( 122 | ! current_user_can( $cap[0], $post_id ) 123 | and ! current_user_can( $cap[1], $post_id ) 124 | ) : 125 | return $post_id; 126 | endif; 127 | 128 | // OK, we're golden. Now let's save some data. 129 | $freeze_updates = FeedWordPress::post( 'freeze_updates' ); 130 | if ( ! is_null( $freeze_updates ) ) : 131 | update_post_meta( 132 | $post_id, 133 | '_syndication_freeze_updates', 134 | sanitize_meta( '_syndication_freeze_updates', $freeze_updates, 'post' ) 135 | ); 136 | $ret = $freeze_updates; 137 | 138 | // If you make manual edits through the WordPress editing 139 | // UI then they should be run through normal WP formatting 140 | // filters. 141 | update_post_meta( $post_id, '_feedwordpress_formatting_filters', 'yes' ); 142 | else : 143 | delete_post_meta( $post_id, '_syndication_freeze_updates' ); 144 | $ret = NULL; 145 | endif; 146 | 147 | do_action( 'feedwordpress_save_edit_controls', $post_id ); 148 | 149 | return $ret; 150 | } /* function feedwordpress_save_edit_controls() */ 151 | -------------------------------------------------------------------------------- /feedwordpressboilerplatereformatter.class.php: -------------------------------------------------------------------------------- 1 | Posts & Links > Boilerplate / Credits 5 | * 6 | * @author C. Johnson 7 | * 8 | * @see feedwordpressboilerplatereformatter.shortcode.functions.php 9 | * 10 | * @version 2020.0120 11 | */ 12 | 13 | class FeedWordPressBoilerplateReformatter { 14 | var $id, $element; 15 | 16 | public function __construct ($id = NULL, $element = 'post') { 17 | $this->id = $id; 18 | $this->element = $element; 19 | } 20 | 21 | function shortcode_methods () { 22 | return array( 23 | 'source' => 'source_link', 24 | 'source-name' => 'source_name', 25 | 'source-url' => 'source_url', 26 | 'original-link' => 'original_link', 27 | 'original-url' => 'original_url', 28 | 'author' => 'source_author_link', 29 | 'author-name' => 'source_author', 30 | 'feed-setting' => 'source_setting', 31 | ); 32 | } 33 | function do_shortcode ($template) { 34 | $codes = $this->shortcode_methods(); 35 | 36 | // Register shortcodes relative to this object/post ID/element. 37 | foreach ($codes as $code => $method) : 38 | add_shortcode($code, array($this, $method)); 39 | endforeach; 40 | 41 | $template = do_shortcode($template); 42 | 43 | // Unregister shortcodes. 44 | foreach ($codes as $code => $method) : 45 | remove_shortcode($code); 46 | endforeach; 47 | 48 | return $template; 49 | } 50 | 51 | function source_name ($atts) { 52 | $param = shortcode_atts(array( 53 | 'original' => NULL, 54 | ), $atts); 55 | return get_syndication_source($param['original'], $this->id); 56 | } 57 | function source_url ($atts) { 58 | $param = shortcode_atts(array( 59 | 'original' => NULL, 60 | ), $atts); 61 | return get_syndication_source_link($param['original'], $this->id); 62 | } 63 | function source_link ($atts) { 64 | $arg0 = (( is_array($atts) and isset($atts[0]) ) ? strtolower($atts[0]) : '' ); 65 | switch ($arg0) : 66 | case '-name' : 67 | $ret = $this->source_name($atts); 68 | break; 69 | case '-url' : 70 | $ret = $this->source_url($atts); 71 | break; 72 | default : 73 | /** @var array Never used. */ 74 | $param = shortcode_atts( 75 | array( 76 | 'original' => NULL, 77 | ), 78 | $atts ); 79 | if ('title' == $this->element) : 80 | $ret = $this->source_name( $atts ); 81 | else : 82 | $ret = ''.htmlspecialchars($this->source_name($atts)).''; 83 | endif; 84 | endswitch; 85 | return $ret; 86 | } 87 | 88 | function source_setting ($atts) { 89 | $param = shortcode_atts(array( 90 | 'key' => NULL, 91 | ), $atts); 92 | return get_feed_meta($param['key'], $this->id); 93 | } 94 | function original_link ($atts, $text) { 95 | $url = $this->original_url($atts); 96 | return ''.do_shortcode($text).''; 97 | } 98 | function original_url ($atts) { 99 | return get_syndication_permalink($this->id); 100 | } 101 | function source_author ($atts) { 102 | return get_the_author(); 103 | } 104 | function source_author_link ($atts) { 105 | $arg0 = (( is_array($atts) and isset($atts[0]) ) ? strtolower($atts[0]) : '' ); 106 | switch ($arg0) : 107 | case '-name' : 108 | $ret = $this->source_author($atts); 109 | break; 110 | default : 111 | global $authordata; // Janky. 112 | if ('title' == $this->element) : 113 | $ret = $this->source_author($atts); 114 | else : 115 | $ret = get_the_author(); 116 | $url = get_author_posts_url((int) $authordata->ID, (int) $authordata->user_nicename); 117 | if ($url) : 118 | $ret = '' 120 | .$ret 121 | .''; 122 | endif; 123 | endif; 124 | endswitch; 125 | return $ret; 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /feedwordpressboilerplatereformatter.shortcode.functions.php: -------------------------------------------------------------------------------- 1 | ]+ )? >/xi', $template)) : 15 | $template = '

    '.$template.'

    '; 16 | endif; 17 | 18 | $ref = new FeedWordPressBoilerplateReformatter($id, $element); 19 | return $ref->do_shortcode($template); 20 | } /* add_boilerplate_reformat() */ 21 | 22 | /** 23 | * function add_boilerplate_simple: look for any relevant Boilerplate / Credits template text to add 24 | * to elements (post body, excerpt, title...) of a post being displayed in WordPress theme code. 25 | * 26 | * @uses is_syndicated() 27 | * @uses get_feed_meta() 28 | * @uses get_option() 29 | * @uses add_boilerplate_reformat() 30 | * 31 | * @param string $element indicates the element of the post 'post' (= main body), 'excerpt', or 'title' 32 | * @param string $title provides the text of the element waiting for boilerplate to be inserted 33 | * @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop) 34 | * @return string provides the reformatted text, including any boilerplate text that has been inserted 35 | */ 36 | function add_boilerplate_simple ($element, $title, $id = NULL) { 37 | if (is_syndicated($id)) : 38 | $meta = get_feed_meta('boilerplate rules', $id); 39 | if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif; 40 | 41 | if ( !is_array($meta) or empty($meta)) : 42 | $meta = get_option('feedwordpress_boilerplate'); 43 | endif; 44 | 45 | if (is_array($meta) and !empty($meta)) : 46 | foreach ($meta as $rule) : 47 | if ($element==$rule['element']) : 48 | $rule['template'] = add_boilerplate_reformat($rule['template'], $element, $id); 49 | 50 | if ('before'==$rule['placement']) : 51 | $title = $rule['template'] . ' ' . $title; 52 | else : 53 | $title = $title . ' ' . $rule['template']; 54 | endif; 55 | endif; 56 | endforeach; 57 | endif; 58 | endif; 59 | return $title; 60 | } /* function add_boilerplate_simple() */ 61 | 62 | /** 63 | * function add_boilerplate_title: filter hook for the_title to add Boilerplate / Credit text, 64 | * if any is set, for the title of syndicated posts 65 | * 66 | * @uses add_boilerplate_simple() 67 | * 68 | * @param string $title contains the text of the title of the post being displayed 69 | * @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop) 70 | * @return string provides the text of the title, reformatted to include any relevant boilerplate text 71 | */ 72 | function add_boilerplate_title ($title, $id = NULL) { 73 | return add_boilerplate_simple('title', $title, $id); 74 | } /* function add_boilerplate_title () */ 75 | 76 | /** 77 | * function add_boilerplate_excerpt: filter hook for the_excerpt to add Boilerplate / Credit text, 78 | * if any is set, for the excerpt of syndicated posts 79 | * 80 | * @uses add_boilerplate_simple() 81 | * 82 | * @param string $excerpt contains the text of the excerpt of the post being displayed 83 | * @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop) 84 | * @return string provides the text of the excerpt, reformatted to include any relevant boilerplate text 85 | */ 86 | function add_boilerplate_excerpt ($title, $id = NULL) { 87 | return add_boilerplate_simple('excerpt', $title, $id); 88 | } /* function add_boilerplate_excerpt () */ 89 | 90 | /** 91 | * function add_boilerplate_content: filter hook for the_content to add Boilerplate / Credit text, 92 | * if any is set, for the excerpt of syndicated posts 93 | * 94 | * @uses is_syndicated() 95 | * @uses get_feed_meta() 96 | * @uses get_option() 97 | * @uses add_boilerplate_reformat() 98 | * 99 | * @param string $content contains the text content of the post being displayed 100 | * @return string provides the text content, reformatted to include any relevant boilerplate text 101 | */ 102 | function add_boilerplate_content ($content) { 103 | if (is_syndicated()) : 104 | $meta = get_feed_meta('boilerplate rules'); 105 | if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif; 106 | 107 | if ( !is_array($meta) or empty($meta)) : 108 | $meta = get_option('feedwordpress_boilerplate'); 109 | endif; 110 | 111 | if (is_array($meta) and !empty($meta)) : 112 | foreach ($meta as $rule) : 113 | if ('post'==$rule['element']) : 114 | $rule['template'] = add_boilerplate_reformat($rule['template'], 'post'); 115 | 116 | if ('before'==$rule['placement']) : 117 | $content = $rule['template'] . "\n" . $content; 118 | else : 119 | $content = $content . "\n" . $rule['template']; 120 | endif; 121 | endif; 122 | endforeach; 123 | endif; 124 | endif; 125 | return $content; 126 | } /* add_boilerplate_content () */ 127 | -------------------------------------------------------------------------------- /feedwordpressdiagnostic.class.php: -------------------------------------------------------------------------------- 1 | uri(); 18 | 19 | // check for effects of an effective-url filter 20 | $effectiveUrl = $link->uri( array( 'fetch' => true ) ); 21 | if ( $url != $effectiveUrl ) : $url .= ' | ' . $effectiveUrl; endif; 22 | 23 | $mesgs = $wpError->get_error_messages(); 24 | foreach ( $mesgs as $mesg ) : 25 | $mesg = esc_html( $mesg ); 26 | FeedWordPress::diagnostic( 27 | 'updated_feeds:errors', 28 | "Feed Error: [{$url}] update returned error: $mesg" 29 | ); 30 | 31 | $hours = get_option( 'feedwordpress_diagnostics_persistent_errors_hours', 2 ); 32 | $span = ( $error['ts'] - $error['since'] ); 33 | 34 | if ( $span >= ( $hours * 60 * 60 ) ) : 35 | $since = date( 'r', $error['since'] ); 36 | /** @var string Never used. */ 37 | $mostRecent = date( 'r', $error['ts'] ); // never used?... (gwyneth 20230919) 38 | FeedWordPress::diagnostic( 39 | 'updated_feeds:errors:persistent', 40 | "Feed Update Error: [{$url}] returning errors" 41 | ." since {$since}:
    $mesg", 42 | $url, 43 | $error['since'], 44 | $error['ts'] 45 | ); 46 | endif; 47 | endforeach; 48 | } /* FeedWordPressDiagnostic::feed_error() */ 49 | 50 | /** 51 | * Returns an array with the list of administrator emails for this site. 52 | * 53 | * @param int|string $id Current blog ID (for multisite installations). 54 | * 55 | * @return array Array with all email addresses for this blog. 56 | * 57 | * @uses get_users_of_blog() 58 | * 59 | * @note This uses the deprecated WP function `get_users_of_blog()`, which 60 | * should be replaced with `get_users()`, which, however, has quite more 61 | * intricate syntax (and customisation!). 62 | * 63 | * It might be even possible to retrieve everything in a single call: 64 | * ``` 65 | * return get_users( 66 | * array( 67 | * 'role__in' => 'administrator', 68 | * 'capability__in' => 'administrator', 69 | * 'fields' => 'user_email', 70 | * 'count_total' => false // no need to count them; improves performance. 71 | * ) 72 | * ); 73 | * ``` 74 | * 75 | * Alternatively, the function `admin_emails()` may simply be marked as deprecated and 76 | * `get_users()` used instead. This requires debugging! (gwyneth 20230919) 77 | */ 78 | public static function admin_emails( $id = '' ) { 79 | // deprecated, see comment on the function description! (gwyneth 20230919) 80 | $users = get_users_of_blog( $id ); 81 | $recipients = array(); 82 | foreach ( $users as $user ) : 83 | $user_id = ( isset( $user->user_id ) ? $user->user_id : $user->ID ); 84 | $dude = new WP_User( $user_id ); 85 | if ( $dude->has_cap('administrator') ) : 86 | if ( $dude->user_email ) : 87 | $recipients[] = $dude->user_email; 88 | endif; 89 | endif; 90 | endforeach; 91 | return $recipients; 92 | } /* FeedWordPressDiagnostic::admin_emails() */ 93 | 94 | public static function noncritical_bug ($varname, $var, $line, $file = NULL) { 95 | if ( FEEDWORDPRESS_DEBUG ) : // halt only when we are doing debugging 96 | self::critical_bug($varname, $var, $line, $file); 97 | endif; 98 | } /* FeedWordPressDiagnostic::noncritical_bug () */ 99 | 100 | public static function critical_bug ($varname, $var, $line, $file = NULL) { 101 | global $wp_version; 102 | 103 | if ( !is_null($file)) : 104 | $location = "line # {$line} of ".basename($file); 105 | else : 106 | $location = "line # {$line}"; 107 | endif; 108 | 109 | print '

    Critical error: There may be a bug in FeedWordPress. Please contact the author and paste the following information into your e-mail:

    '; 110 | print "\n
    ";
    111 | 		print "Triggered at " . esc_html($location) . "\n";
    112 | 		print "FeedWordPress: " . esc_html( FEEDWORDPRESS_VERSION ) . "\n";
    113 | 		print "WordPress:     " . esc_html( $wp_version ) . "\n";
    114 | 		print "PHP:           " . esc_html( phpversion() ) . "\n";
    115 | 		print "Error data:    ";
    116 | 		print esc_html($varname) . ": " . esc_html( MyPHP::val( $var ) ) . "\n";
    117 | 		print "\n
    "; 118 | die; 119 | } /* FeedWordPressDiagnostic::critical_bug () */ 120 | 121 | public static function is_on ($level) { 122 | $show = get_option('feedwordpress_diagnostics_show', array()); 123 | if ( ! is_array( $show ) ) { 124 | $show = array( $show ); 125 | } 126 | 127 | return ( in_array( $level, $show ) ); 128 | } /* FeedWordPressDiagnostic::is_on () */ 129 | 130 | } /* class FeedWordPressDiagnostic */ 131 | -------------------------------------------------------------------------------- /feedwordpresshtml.class.php: -------------------------------------------------------------------------------- 1 | ]*) 6 | ($attr)= 7 | ) 8 | ( 9 | \s*(\"|') 10 | (((?!\\6).)*) 11 | \\6([^>]*>) 12 | | 13 | \s*(((?!/>)[^\s>])*) 14 | ([^>]*>) 15 | ) 16 | :ix"; 17 | } /* function FeedWordPressHTML::attributeRegex () */ 18 | 19 | static function attributeMatch ($matches) { 20 | for ($i = 0; $i <= 12; $i++) : 21 | if ( !isset($matches[$i])) : 22 | $matches[$i] = ''; 23 | endif; 24 | endfor; 25 | 26 | $suffix = $matches[12].$matches[9]; 27 | $value = $matches[10].$matches[7]; 28 | 29 | return array( 30 | "tag" => $matches[3], 31 | "attribute" => $matches[4], 32 | "value" => $value, 33 | "quote" => $matches[6], 34 | "prefix" => $matches[1].$matches[6], 35 | "suffix" => $matches[6].$suffix, 36 | "before_attribute" => $matches[2], 37 | "after_attribute" => $suffix, 38 | ); 39 | } /* function FeedWordPressHTML::attributeMatch () */ 40 | 41 | static function tagWithAttributeRegex ($tag, $attr, $value, $closing = true) { 42 | return ":( 43 | (<($tag)\s+[^>]*) 44 | ($attr)= 45 | ) 46 | ( 47 | \s*(\"|') 48 | ((((?!\\6).)*\s)*($value)(\s((?!\\6).)*)*) 49 | \\6([^>]*>) 50 | | 51 | \s*((?!/>)($value)) 52 | ([^>]*>) 53 | )".($closing ? " 54 | (((?!).)*) 55 | () 56 | " : "")." 57 | :ix"; 58 | } /* FeedWordPressHTML::tagWithAttributeRegex () */ 59 | 60 | static function tagWithAttributeMatch ($matches, $closing = true) { 61 | for ($i = 0; $i <= 21; $i++) : 62 | if ( !isset($matches[$i])) : 63 | $matches[$i] = ''; 64 | endif; 65 | endfor; 66 | 67 | $suffix = $matches[16].$matches[13]; 68 | $value = $matches[14].$matches[7]; 69 | 70 | return array( 71 | "full" => $matches[0], 72 | "tag" => $matches[3], 73 | "attribute" => $matches[4], 74 | "value" => $value, 75 | "quote" => $matches[6], 76 | "prefix" => $matches[1].$matches[6], 77 | "suffix" => $matches[6].$suffix, 78 | "before_attribute" => $matches[2], 79 | "after_attribute" => $suffix, 80 | "open_tag" => $matches[1].$matches[6].$value.$matches[6].$suffix, 81 | "content" => ($closing ? $matches[17] : NULL), 82 | "close_tag" => ($closing ? $matches[20] : NULL), 83 | ); 84 | 85 | } /* FeedWordPressHTML::tagWithAttributeMatch () */ 86 | } /* class FeedWordPressHTML */ 87 | 88 | -------------------------------------------------------------------------------- /feedwordpresshttpauthenticator.class.php: -------------------------------------------------------------------------------- 1 | 'None'); 17 | 18 | if ($this->have_curl(array('authentication' => 'digest'))) : 19 | $methods = array_merge(array( 20 | 'digest' => 'Digest', 21 | ), $methods); 22 | endif; 23 | 24 | if ( 25 | $this->have_curl(array('authentication' => 'basic')) 26 | or $this->have_streams(array('authentication' => 'basic')) 27 | ) : 28 | $methods = array_merge(array( 29 | 'basic' => 'Basic', 30 | ), $methods); 31 | endif; 32 | 33 | return $methods; 34 | } 35 | 36 | function pre_http_request ($pre, $args, $url) { 37 | $this->args = wp_parse_args($args, array( 38 | 'authentication' => NULL, 39 | 'username' => NULL, 40 | 'password' => NULL, 41 | )); 42 | 43 | // Ruh roh... 44 | $auth = $this->args['authentication']; 45 | if (is_null($auth) or (strlen($auth) == 0)) : 46 | $this->args['authentication'] = '-'; 47 | endif; 48 | 49 | switch ($this->args['authentication']) : 50 | case '-' : 51 | // No HTTP Auth method. Remove this stuff. 52 | $this->args['authentication'] = NULL; 53 | $this->args['username'] = NULL; 54 | $this->args['password'] = NULL; 55 | break; 56 | case 'basic' : 57 | if ($this->have_curl($args, $url)) : 58 | // Don't need to do anything. http_api_curl hook takes care 59 | // of it. 60 | break; 61 | elseif ($this->have_streams($args, $url)) : 62 | // curl has a nice native way to jam in the username and 63 | // passwd but streams and fsockopen do not. So we have to 64 | // make a recursive call with the credentials in the URL. 65 | // Wee ha! 66 | $method = $this->args['authentication']; 67 | $credentials = $this->args['username']; 68 | if ( !is_null($this->args['password'])) : 69 | $credentials .= ':'.$args['password']; 70 | endif; 71 | 72 | // Remove these so we don't recurse all the way down 73 | unset($this->args['authentication']); 74 | unset($this->args['username']); 75 | unset($this->args['password']); 76 | 77 | $url = preg_replace('!(https?://)!', '$1'.$credentials.'@', $url); 78 | 79 | // Subsidiary request 80 | $pre = wp_remote_request($url, $this->args); 81 | break; 82 | endif; 83 | case 'digest' : 84 | if ($this->have_curl($args, $url)) : 85 | // Don't need to do anything. http_api_curl hook takes care 86 | // of it. 87 | break; 88 | endif; 89 | default : 90 | if (is_callable('WP_Http', '_get_first_available_transport')) : 91 | $trans = WP_Http::_get_first_available_transport($args, $url); 92 | if ( ! $trans) : 93 | $trans = WP_Http::_get_first_available_transport(array(), $url); 94 | endif; 95 | elseif (is_callable('WP_Http', '_getTransport')) : 96 | $transports = WP_Http::_getTransport($args); // absolutely deprecated & removed. (gwyneth 20230920) 97 | $trans = get_class(reset($transports)); 98 | else : 99 | $trans = 'HTTP'; 100 | endif; 101 | 102 | $pre = new WP_Error('http_request_failed', 103 | sprintf( 104 | __('%s cannot use %s authentication with the %s transport.'), 105 | __CLASS__, 106 | $args['authentication'], 107 | $trans 108 | ) 109 | ); 110 | endswitch; 111 | 112 | return $pre; 113 | } /* FeedWordPressHTTPAuthenticator::pre_http_request () */ 114 | 115 | function have_curl ($args, $url = NULL) { 116 | return WP_Http_Curl::test($args); 117 | } 118 | 119 | function have_streams ($args, $url = NULL) { 120 | return WP_Http_Streams::test($args); 121 | } 122 | 123 | function need_curl ($args) { 124 | $args = wp_parse_args($args, array( 125 | 'authentication' => NULL, 126 | )); 127 | 128 | switch ($args['authentication']) : 129 | case 'digest' : 130 | $use = true; 131 | break; 132 | default : 133 | $use = false; 134 | endswitch; 135 | return $use; 136 | } /* FeedWordPressHTTPAuthenticator::need_curl () */ 137 | 138 | function digest_do_it ($use, $args) { 139 | return $this->if_curl($use, $args, true); 140 | } /* FeedWordPerssHTTPAuthenticator::digest_do_it () */ 141 | 142 | function digest_dont ($use, $args) { 143 | return $this->if_curl($use, $args, false); 144 | } /* FeedWordPressHTTPAuthenticator::digest_dont () */ 145 | 146 | function if_curl ($use, $args, $what) { 147 | if ($this->need_curl($args)) : 148 | $use = $what; 149 | endif; 150 | return $use; 151 | } /* FeedWordPressHTTPAuthenticator::if_curl () */ 152 | 153 | function set_auth_options ($handle, $r, $url) { 154 | if ('digest'==$this->args['authentication']) : 155 | curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); 156 | endif; 157 | 158 | if ( !is_null($this->args['username'])) : 159 | $userPass = $this->args['username']; 160 | if ( !is_null($this->args['password'])) : 161 | $userPass .= ':'.$this->args['password']; 162 | endif; 163 | 164 | curl_setopt($handle, CURLOPT_USERPWD, $userPass); 165 | endif; 166 | 167 | } /* FeedWordPressHTTPAuthenticator::set_auth_options() */ 168 | 169 | } /* class FeedWordPressHTTPAuthenticator */ 170 | -------------------------------------------------------------------------------- /feedwordpresslocalpost.class.php: -------------------------------------------------------------------------------- 1 | post = $post; // current post in loop 12 | elseif (is_object($p)) : 13 | $this->post = $p; 14 | else : 15 | $this->post = get_post($p); 16 | endif; 17 | } 18 | 19 | public function id () { 20 | if (is_null($this->post) or !is_object($this->post)) : 21 | return NULL; 22 | else : 23 | return $this->post->ID; 24 | endif; 25 | } /* FeedWordPressLocalPost::id () */ 26 | 27 | public function meta ($what, $params = array()) { 28 | 29 | // -=-=-= 1. INITIAL SETUP. =-=-=- 30 | $params = wp_parse_args($params, array( 31 | "single" => true, 32 | "default" => NULL, 33 | "global" => NULL, 34 | "unproxied setting" => NULL, 35 | "unproxy" => false, 36 | )); 37 | 38 | // If we got put through the_content without a current 39 | // $post object set, then bail out immediately. 40 | if (is_null($this->post) or !is_object($this->post)) : 41 | return $params['default']; 42 | endif; 43 | 44 | // This is a little weird, just bear with me here. 45 | $results = array(); 46 | 47 | // Has this been left up to the admin setting? 48 | if (is_null($params['unproxy'])) : 49 | $params['unproxy'] = FeedWordPress::use_aggregator_source_data(); 50 | endif; 51 | 52 | // -=-=-= 2. GET DATA FROM THE PROXIMATE OR THE ULTIMATE SOURCE. =-=-=- 53 | 54 | // Now if we are supposed to look for ultimate source data (e.g. from 55 | // ... elements), do so here. 56 | if ($params['unproxy']) : 57 | if ( !is_string($params['unproxied setting'])) : 58 | // Default pattern for unproxied settings: {$name}_original 59 | $params['unproxied setting'] = $what . '_original'; 60 | endif; 61 | 62 | // Now see if there's anything in postmeta from our ultimate source. 63 | // If so, then we can cut out the middle man here. 64 | $results = get_post_meta($this->post->ID, /*key=*/ $params['unproxied setting'], /*single=*/ false); 65 | endif; 66 | 67 | // If we weren't looking for ultimate source data, or if there wasn't 68 | // any recorded, then grab this from the data for the proximate source. 69 | if (empty($results)) : 70 | $results = get_post_meta($this->post->ID, /*key=*/ $what, /*single=*/ false); 71 | endif; 72 | 73 | // -=-=-= 3. DEAL WITH THE RESULTS, IF ANY, OR FALLBACK VALUES. =-=-=- 74 | 75 | // If we have results now, cool. Just pass them back. 76 | if ( !empty($results)) : 77 | $ret = ($params['single'] ? $results[0] : $results); 78 | 79 | // If we got no results but we have a fallback global setting, cool. Use 80 | // that. Jam it into a singleton array for queries expecting an array of 81 | // results instead of a scalar result. 82 | elseif (is_string($params['global']) and strlen($params['global']) > 0) : 83 | $opt = get_option($params['global'], $params['default']); 84 | $ret = ($params['single'] ? $opt : array($opt)); 85 | 86 | // If we got no results and we have no fallback global setting, pass 87 | // back a default value for single-result queries, or an empty array for 88 | // multiple-result queries. 89 | else : 90 | $ret = ($params['single'] ? $params['default'] : array()); 91 | endif; 92 | 93 | return $ret; 94 | } 95 | 96 | public function is_syndicated () { 97 | return ( !is_null($this->feed_id(/*single=*/ false))); 98 | } 99 | 100 | public function syndication_permalink () { 101 | return $this->meta('syndication_permalink'); 102 | } 103 | 104 | public function feed () { 105 | global $feedwordpress; 106 | if (is_object($feedwordpress) and method_exists($feedwordpress, 'subscription')) : 107 | $this->link = $feedwordpress->subscription($this->feed_id()); 108 | endif; 109 | return $this->link; 110 | } 111 | 112 | public function feed_id () { 113 | return $this->meta('syndication_feed_id'); 114 | } 115 | 116 | public function syndication_feed ($original = NULL) { 117 | return $this->meta('syndication_feed', array("unproxy" => $original)); 118 | } 119 | 120 | public function syndication_feed_guid ($original = NULL) { 121 | $ret = $this->meta('syndication_source_id', array("unproxy" => $original)); 122 | 123 | // If this is blank, fall back to the full URL of the feed 124 | if (is_null($ret) or strlen(trim($ret))==0) : 125 | $ret = get_syndication_feed(); 126 | endif; 127 | 128 | return $ret; 129 | } 130 | 131 | public function syndication_source ($original = NULL) { 132 | $ret = $this->meta('syndication_source', array("unproxy" => $original)); 133 | 134 | // If this is blank, fall back to a prettified URL for the blog. 135 | if (is_null($ret) or strlen(trim($ret)) == 0) : 136 | $ret = feedwordpress_display_url($this->syndication_source_link()); 137 | endif; 138 | 139 | return $ret; 140 | } 141 | 142 | public function syndication_source_link ($original = NULL) { 143 | return $this->meta('syndication_source_uri', array("unproxy" => $original)); 144 | } 145 | 146 | public function is_exposed_to_formatting_filters () { 147 | 148 | return ( 149 | ! $this->is_syndicated() 150 | or ( 151 | 'yes' == $this->meta( 152 | '_feedwordpress_formatting_filters', 153 | array( 154 | 'global' => 'feedwordpress_formatting_filters', 155 | 'default' => 'no', 156 | ) 157 | ) 158 | ) 159 | ); 160 | 161 | } /* FeedWordPressLocalPost::is_exposed_to_formatting_filters () */ 162 | 163 | 164 | public function content () { 165 | if (is_null($this->post) or !is_object($this->post)) : 166 | $post_content = NULL; 167 | $post_id = NULL; 168 | else : 169 | $post_content = $this->post->post_content; 170 | $post_id = $this->post->ID; 171 | endif; 172 | return apply_filters('the_content', $post_content, $post_id); 173 | } 174 | 175 | public function title () { 176 | if (is_null($this->post) or !is_object($this->post)) : 177 | $post_title = NULL; 178 | $post_id = NULL; 179 | else : 180 | $post_title = $this->post->post_title; 181 | $post_id = $this->post->ID; 182 | endif; 183 | return apply_filters('the_title', $post_title, $post_id); 184 | } 185 | 186 | public function guid () { 187 | if (is_null($this->post) or !is_object($this->post)) : 188 | $post_guid = NULL; 189 | else : 190 | $post_guid = $this->post->guid; 191 | endif; 192 | return apply_filters('get_the_guid', $post_guid); 193 | } 194 | 195 | public function get_categories () { 196 | if (is_null($this->post) or !is_object($this->post)) : 197 | return array(); 198 | endif; 199 | 200 | $terms = wp_get_object_terms( 201 | $this->post->ID, 202 | get_taxonomies(array( 203 | 'public' => true, 204 | ), 'names'), 205 | 'all' 206 | ); 207 | $rootUrl = get_bloginfo('url'); 208 | 209 | $cats = array(); 210 | foreach ($terms as $term) : 211 | $taxUrl = MyPHP::url($rootUrl, array("taxonomy" => $term->taxonomy)); 212 | //array("taxonomy" => $term->taxonomy )); 213 | $cats[] = new SimplePie_Category( 214 | /*term=*/ $term->slug, 215 | /*scheme=*/ $taxUrl, 216 | /*label=*/ $term->name 217 | ); 218 | endforeach; 219 | return $cats; 220 | } 221 | 222 | } /* class FeedWordPressLocalPost */ 223 | 224 | -------------------------------------------------------------------------------- /feedwordpressparsedpostmeta.class.php: -------------------------------------------------------------------------------- 1 | s = $s; 12 | $this->reset(); 13 | } 14 | 15 | function reset () { 16 | $this->parsed = NULL; 17 | 18 | $this->ptr = 0; 19 | $this->paren = 0; 20 | $this->ptrEOS = strlen($this->s); 21 | 22 | $this->delimCount['CDATA'] = preg_match_all('/\$/', $this->s, $this->delims['CDATA'], PREG_OFFSET_CAPTURE); 23 | $this->delimPtr['CDATA'] = 0; 24 | 25 | $this->delimCount['EXPR'] = preg_match_all('/[()\s]/', $this->s, $this->delims['EXPR'], PREG_OFFSET_CAPTURE); 26 | $this->delimPtr['EXPR'] = 0; 27 | } 28 | 29 | function look () { return $this->s[$this->ptr]; } 30 | function drop () { $this->anchor = $this->ptr; } 31 | function take () { return substr($this->s, $this->anchor, ($this->ptr - $this->anchor)); } 32 | function EOS () { return ($this->ptr >= $this->ptrEOS); } 33 | 34 | function nextDelim ($which) { 35 | $N = $this->delimCount[$which]; $ptr = $this->delimPtr[$which]; 36 | 37 | $next = -1; 38 | while ( ($ptr < $N) and ($next < $this->ptr) ) : 39 | $next = $this->delims[$which][0][$ptr][1]; 40 | $ptr++; 41 | endwhile; 42 | $this->delimPtr[$which] = $ptr; 43 | 44 | if ($next < $this->ptr) : 45 | $next = $this->ptrEOS; 46 | endif; 47 | return $next; 48 | } 49 | 50 | function substitute_terms ($post, $piece, $values = NULL) { 51 | $terms = array(); // never used. (gwyneth 20230920) 52 | if ('EXPR'==$piece[0]) : 53 | // Parameter stored in $piece[1] 54 | $param = $piece[1]; 55 | if (is_string($param)) : 56 | if ( !isset($values[$param])) : 57 | $values[$param] = $post->query($param); 58 | endif; 59 | $term = $param; 60 | $results = $values[$param]; 61 | else : 62 | list($results, $term, $values) = $this->substitute_terms($post, $piece[1], $values); 63 | endif; 64 | 65 | // Filtering function, if any, stored in $piece[2] 66 | if (isset($piece[2])) : 67 | $filter = $post->substitution_function(trim(strtolower($piece[2]))); 68 | if ( !is_null($filter)) : 69 | foreach ($results as $key => $result) : 70 | $results[$key] = $filter($result); 71 | endforeach; 72 | else : 73 | $results = array( 74 | "[[ERR: No such function (".$piece[2].")]]", 75 | ); 76 | endif; 77 | endif; 78 | 79 | elseif ('CDATA'==$piece[0]) : 80 | // Literal string stored in $piece[1] 81 | $results = array($piece[1]); 82 | $term = NULL; 83 | endif; 84 | return array($results, $term, $values); 85 | } 86 | 87 | function do_substitutions ($post, $in = NULL, $scratchpad = NULL) { 88 | if (is_null($in)) : 89 | $in = $this->get(); 90 | endif; 91 | 92 | if (count($in) > 0) : 93 | $out = array(); 94 | 95 | // Init. results set if not already initialized. 96 | if (is_null($scratchpad)) : 97 | $scratchpad = array(array('', array())); 98 | endif; 99 | 100 | // Grab the first 101 | $piece = array_shift($in); 102 | 103 | foreach ($scratchpad as $key => $scratch) : 104 | $line = $scratch[0]; 105 | $element_values = $scratch[1]; 106 | 107 | switch ($piece[0]) : 108 | case 'CDATA' : 109 | $subs = array($piece[1]); 110 | $term = NULL; 111 | break; 112 | case 'EXPR' : 113 | list($subs, $term, $element_values) = $this->substitute_terms($post, $piece, $element_values); 114 | break; 115 | endswitch; 116 | 117 | $constrained_values = $element_values; 118 | foreach ($subs as $sub) : 119 | 120 | if (isset($term)) : 121 | $constrained_values[$term] = array($sub); 122 | endif; 123 | 124 | $out[] = array($line . $sub, $constrained_values); 125 | endforeach; 126 | 127 | endforeach; 128 | 129 | if (count($in) > 0) : 130 | $out = $this->do_substitutions($post, $in, $out); 131 | endif; 132 | else : 133 | $out = NULL; 134 | endif; 135 | 136 | // Now that we are done, strip out the namespace elements. 137 | if (is_array($out)) : 138 | foreach ($out as $idx => $line) : 139 | if (is_array($line)) : 140 | $out[$idx] = $line[0]; 141 | endif; 142 | endforeach; 143 | endif; 144 | 145 | return $out; 146 | } 147 | 148 | function get ($idx = NULL) { 149 | $ret = $this->parse(); 150 | if ($idx) : $ret = $ret[$idx]; endif; 151 | 152 | return $ret; 153 | } 154 | 155 | function parse () { 156 | if (is_null($this->parsed)) : 157 | $out = array(); 158 | 159 | $this->reset(); 160 | while ( ! $this->EOS()) : 161 | switch ($this->look()) : 162 | case '$' : 163 | $this->ptr++; 164 | $out[] = $this->EXPR(); 165 | break; 166 | default : 167 | $out[] = $this->CDATA(); 168 | endswitch; 169 | endwhile; 170 | 171 | $this->parsed = $out; 172 | endif; 173 | return $this->parsed; 174 | } 175 | 176 | function CDATA () { 177 | $this->drop(); 178 | $this->ptr = $this->nextDelim('CDATA'); 179 | return array(__FUNCTION__, $this->take()); 180 | } /* FeedWordPressParsedPostMeta::CDATA() */ 181 | 182 | function EXPR () { 183 | $ret = array(__FUNCTION__); 184 | $paren0 = $this->paren; 185 | $this->drop(); 186 | 187 | $ptr0 = $this->ptr; 188 | 189 | $complete = false; 190 | while ( ! $this->EOS() and ! $complete) : 191 | $tok = $this->look(); 192 | switch ($tok) : 193 | case '(' : 194 | 195 | $fun = $this->take(); 196 | 197 | // We're at the open paren; skip ahead past that. 198 | $this->ptr++; 199 | 200 | // And indent us one level in. 201 | $this->paren++; 202 | 203 | $delta = $this->EXPR(); 204 | if (isset($delta[2])) : 205 | $ret[1] = $delta; 206 | else : 207 | $ret[1] = $delta[1]; 208 | endif; 209 | 210 | if (strlen(trim($fun)) > 0) : 211 | $ret[2] = trim($fun); 212 | endif; 213 | 214 | // We should be stopped on either a close paren or on EOS. 215 | $this->ptr++; 216 | 217 | // A top level expression terminates 218 | // immediately with the closing of its 219 | // parens. Lower-level expressions may 220 | // have whitespace wrapper, etc. 221 | $complete = ($this->paren <= 0); 222 | 223 | $this->drop(); 224 | break; 225 | 226 | case ')' : 227 | 228 | if ($this->paren > 0) : 229 | $this->paren--; 230 | 231 | $complete = ($this->paren <= $paren0); 232 | 233 | $fun = $this->take(); 234 | if (strlen(trim($fun)) > 0) : 235 | $ret[1] = trim($fun); 236 | endif; 237 | 238 | $this->drop(); 239 | else : 240 | $this->ptr++; 241 | endif; 242 | break; 243 | 244 | case '$' : 245 | if ($ptr0 == $this->ptr) : 246 | // This is an escaped literal $ 247 | $this->ptr++; 248 | $ret = array('CDATA', $tok); 249 | $this->drop(); 250 | $complete = true; 251 | break; 252 | endif; 253 | 254 | default : 255 | if (ctype_space($tok) and ($this->paren <= 0)) : 256 | // A loose $ should be treated as a literal $ 257 | if ($ptr0 == $this->ptr) : 258 | $ret = array('CDATA', '$'); 259 | $this->drop(); 260 | endif; 261 | $complete = true; 262 | else : 263 | $next = $this->nextDelim('EXPR'); 264 | 265 | // Skip ahead to the next potentially interesting character. 266 | if ( !is_null($next)) : 267 | $this->ptr = $next; 268 | else : 269 | $this->ptr = $this->ptrEOS; 270 | endif; 271 | 272 | endif; 273 | endswitch; 274 | endwhile; 275 | 276 | $var = ''; 277 | if ($this->anchor < $this->ptr) : 278 | $var = trim($this->take()); 279 | endif; 280 | if (strlen($var) > 0) : 281 | $ret[1] = $var; 282 | endif; 283 | return $ret; 284 | } /* FeedWordPressParsedPostMeta::EXPR () */ 285 | } /* class FeedWordPressParsedPostMeta */ 286 | 287 | if (basename($_SERVER['SCRIPT_FILENAME'])==basename(__FILE__)) : 288 | $argv = $_SERVER['argv']; 289 | array_shift($argv); 290 | $N = reset($argv); 291 | if (is_numeric($N)) : 292 | array_shift($argv); 293 | else : 294 | $N = 1; 295 | endif; 296 | 297 | $t0 = microtime(/*float=*/ true); 298 | for ($i = 0; $i < $N; $i++) : 299 | $parse = new FeedWordPressParsedPostMeta(implode(" ", $argv)); 300 | $voo = ($parse->parse()); 301 | unset($parse); 302 | endfor; 303 | $t1 = microtime(/*float=*/ true); 304 | 305 | echo "RESULT: "; var_dump($voo); 306 | echo "ELAPSED TIME: "; print number_format(1000.0 * ($t1 - $t0)) . "ms\n"; 307 | echo "CONSUMED MEMORY: "; print number_format(memory_get_peak_usage() / 1024) . "KB\n"; 308 | endif; 309 | 310 | -------------------------------------------------------------------------------- /feedwordpressrpc.class.php: -------------------------------------------------------------------------------- 1 | update($args[1]); 24 | if (is_null($delta)): 25 | return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>."); 26 | else: 27 | $mesg = array(); // unused? (gwyneth 20230920) 28 | return array('flerror' => false, 'message' => "Thanks for the ping.".fwp_update_set_results_message($delta)); 29 | endif; 30 | } 31 | 32 | function validate (&$args) { 33 | global $wp_xmlrpc_server; 34 | 35 | // First two params are username/password 36 | $username = $wp_xmlrpc_server->escape(array_shift($args)); 37 | $password = $wp_xmlrpc_server->escape(array_shift($args)); 38 | 39 | $ret = array(); 40 | // $user is unused. Is it just a return value, or should it be stored somewhere? (gwyneth 20230920) 41 | if ( ! $user = $wp_xmlrpc_server->login($username, $password) ) : 42 | $ret = $wp_xmlrpc_server->error; 43 | elseif ( !current_user_can('manage_links')) : 44 | $ret = new IXR_Error(401, 'Sorry, you cannot change the subscription list.'); 45 | endif; 46 | return $ret; 47 | } 48 | 49 | function subscribe ($args) { 50 | $ret = $this->validate($args); 51 | if (is_array($ret)) : // Success 52 | // The remaining params are feed URLs 53 | foreach ($args as $arg) : 54 | $finder = new FeedFinder($arg, /*verify=*/ false, /*fallbacks=*/ 1); 55 | $feeds = array_values(array_unique($finder->find())); 56 | 57 | if (count($feeds) > 0) : 58 | // $link_id is never used, possibly because it's just a discardable return value. However, 59 | // it _can_ return a WP_Error, so it might make sense to check for it? (gwyneth 20230920) 60 | $link_id = FeedWordPress::syndicate_link( 61 | /*title=*/ feedwordpress_display_url($feeds[0]), 62 | /*homepage=*/ $feeds[0], 63 | /*feed=*/ $feeds[0] 64 | ); 65 | // just to make sure! (gwyneth 20230920) 66 | if ( is_wp_error( $link_id ) ) : 67 | FeedWordPress::diagnostic( 68 | 'fwp-rpc/subscribe', 69 | implode( '|', $link_id->get_error_messages() ) 70 | ); 71 | endif; 72 | $ret[] = array( 73 | 'added', 74 | $feeds[0], 75 | $arg, 76 | ); 77 | else : 78 | $ret[] = array( 79 | 'error', 80 | $arg 81 | ); 82 | endif; 83 | endforeach; 84 | endif; 85 | return $ret; 86 | } /* FeedWordPressRPC::subscribe () */ 87 | 88 | function unsubscribe ($method, $args) { 89 | $ret = $this->validate($args); 90 | if (is_array($ret)) : // Success 91 | // The remaining params are feed URLs 92 | foreach ($args as $arg) : 93 | $link_id = FeedWordPress::find_link($arg); 94 | 95 | if ( ! $link_id) : 96 | $link_id = FeedWordPress::find_link($arg, 'link_url'); 97 | endif; 98 | 99 | if ($link_id) : 100 | $link = new SyndicatedLink($link_id); 101 | 102 | $link->{$method}(); 103 | $ret[] = array( 104 | 'deactivated', 105 | $arg, 106 | ); 107 | else : 108 | $ret[] = array( 109 | 'error', 110 | $arg, 111 | ); 112 | endif; 113 | endforeach; 114 | endif; 115 | return $ret; 116 | } /* FeedWordPress::unsubscribe () */ 117 | 118 | function deactivate ($args) { 119 | return $this->unsubscribe('deactivate', $args); 120 | } /* FeedWordPressRPC::deactivate () */ 121 | 122 | function delete ($args) { 123 | return $this->unsubscribe('delete', $args); 124 | } /* FeedWordPressRPC::delete () */ 125 | 126 | function nuke ($args) { 127 | return $this->unsubscribe('nuke', $args); 128 | } /* FeedWordPressRPC::nuke () */ 129 | } /* class FeedWordPressRPC */ 130 | 131 | -------------------------------------------------------------------------------- /feedwordpresssettingsui.class.php: -------------------------------------------------------------------------------- 1 | 48 | 79 | \n

    \n"; 90 | wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); 91 | wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); 92 | echo "

    \n\n"; 93 | endif; 94 | } /* FeedWordPressSettingsUI::ajax_nonce_fields () */ 95 | 96 | static function fix_toggles_js ($context) { 97 | ?> 98 | 110 | 0 ): 133 | $ext = ".{$type}{$ext}"; 134 | endif; 135 | 136 | if ( strlen( $name ) > 0 ) : 137 | $templates[] = "{$slug}-{$name}{$ext}"; 138 | endif; 139 | $templates[] = "{$slug}{$ext}"; 140 | 141 | do_action( "feedwordpress_get_template_part", $slug, $name, $type, $args ); 142 | 143 | // locate_template 144 | $located = ''; 145 | foreach ( $templates as $template_name ) : 146 | if ( !! $template_name ) : 147 | $templatePath = $feedwordpress->plugin_dir_path( 'templates/' . $template_name ); 148 | if ( is_readable( $templatePath ) ) : 149 | $located = $templatePath; 150 | break; 151 | endif; 152 | endif; 153 | endforeach; 154 | 155 | if ( strlen( $located ) > 0 ) : 156 | load_template( $located, /*require_once=*/ false, /*args=*/ $args ); 157 | endif; 158 | } /* FeedWordPressSettingsUI::get_template_part () */ 159 | 160 | /** 161 | * Generates contextual hovering text with tips for the form fields. 162 | * 163 | * How exactly this works is beyond myself. (gwyneth 20230916) 164 | * 165 | * @param string $id Apparently it's the field's id attribute. 166 | * 167 | */ 168 | static function magic_input_tip_js( $id ) { 169 | if ( ! preg_match( '/^[.#]/', $id ) ) : 170 | $id = '#' . $id; 171 | endif; 172 | ?> 173 | 190 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ID); 47 | if (count($custom) > 0) : 48 | foreach ($custom as $key => $values) : 49 | $idx = 1; 50 | foreach ($values as $value) : 51 | print " "; 56 | print "\n"; 58 | $idx++; 59 | endforeach; 60 | endforeach; 61 | else : 62 | print "\n"; 63 | endif; 64 | print "
    ID:ID); ?>
    GUID:guid); ?>

    Custom Fields

    ".esc_html($key); 52 | if ($idx > 1) : 53 | print esc_html( sprintf( '[%d]', intval( $idx ) ) ); 54 | endif; 55 | print ":
    ".esc_html($value)."
    "; 57 | print "

    No custom fields for this post.

    \n"; 65 | } /* InspectPostMeta::meta_box() */ 66 | } /* class InspectPostMeta */ 67 | 68 | -------------------------------------------------------------------------------- /magpiemocklink.class.php: -------------------------------------------------------------------------------- 1 | link = $rss; 9 | 10 | if (is_array($rss) and isset($rss['simplepie']) and isset($rss['magpie'])) : 11 | $this->simplepie = $rss['simplepie']; 12 | $this->magpie = $rss['magpie']; 13 | else : 14 | $this->magpie = $rss; 15 | endif; 16 | 17 | $this->url = $url; 18 | $this->id = -1; 19 | $this->settings = array( 20 | 'unfamiliar category' => 'default', 21 | 22 | ); 23 | } /* function MagpieMockLink::MagpieMockLink () */ 24 | 25 | function MagpieMockLink( $rss, $url ) { 26 | self::__construct( $rss, $url ); 27 | } 28 | 29 | function poll ($crash_ts = NULL) { 30 | // Do nothing but update copy of feed 31 | $this->simplepie = FeedWordPress::fetch($this->url); 32 | $this->magpie = new MagpieFromSimplePie($this->simplepie); 33 | 34 | $this->link = $this->magpie; 35 | } /* function MagpieMockLink::poll () */ 36 | 37 | function uri ($params = array()) { 38 | return $this->url; 39 | } /* function MagpieMockLink::uri() */ 40 | 41 | function homepage ($fromFeed = true) { 42 | return ( !is_wp_error($this->simplepie) ? $this->simplepie->get_link() : null); 43 | } /* function MagpieMockLink::homepage () */ 44 | 45 | function save_settings ($reload = false) { 46 | // NOOP. 47 | } 48 | } /* class MagpieMockLink */ 49 | 50 | 51 | -------------------------------------------------------------------------------- /performance-page.php: -------------------------------------------------------------------------------- 1 | dispatch = 'feedwordpress_performance'; 9 | $this->filename = __FILE__; 10 | } 11 | 12 | public function has_link () { return false; } 13 | 14 | function display () { 15 | if (FeedWordPress::needs_upgrade()) : 16 | fwp_upgrade_page(); 17 | return; 18 | endif; 19 | 20 | // If this is a POST, validate source and user credentials 21 | FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_performance', /*capability=*/ 'manage_options'); 22 | 23 | if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') : 24 | $this->accept_POST(); 25 | do_action('feedwordpress_admin_page_performance_save', null, $this); 26 | endif; 27 | 28 | //////////////////////////////////////////////// 29 | // Prepare settings page /////////////////////// 30 | //////////////////////////////////////////////// 31 | 32 | $this->display_update_notice_if_updated('Performance'); 33 | 34 | $this->open_sheet('FeedWordPress Performance'); 35 | ?> 36 |
    37 | __('Performance'), 40 | ); 41 | 42 | foreach ($boxes_by_methods as $method => $title) : 43 | add_meta_box( 44 | /*id=*/ 'feedwordpress_'.$method, 45 | /*title=*/ $title, 46 | /*callback=*/ array('FeedWordPressPerformancePage', $method), 47 | /*page=*/ $this->meta_box_context(), 48 | /*context=*/ $this->meta_box_context() 49 | ); 50 | endforeach; 51 | do_action('feedwordpress_admin_page_performance_meta_boxes', $this); 52 | ?> 53 |
    54 | meta_box_context(), $this->meta_box_context(), $this); 56 | ?> 57 |
    58 |
    59 | 60 | close_sheet(); 62 | } /* FeedWordPressPerformancePage::display () */ 63 | 64 | function accept_POST () { 65 | global $feedwordpress; 66 | 67 | if ( ! is_null( FeedWordPress::post( 'create_index' ) ) ) : 68 | FeedWordPress::create_guid_index(); 69 | $this->updated = __('guid column index created on database table.'); 70 | endif; 71 | if ( ! is_null( FeedWordPress::post( 'remove_index' ) ) ) : 72 | FeedWordPress::remove_guid_index(); 73 | $this->updated = __('guid column index removed from database table.'); 74 | endif; 75 | 76 | if ( ! is_null( FeedWordPress::post( 'clear_cache' ) ) ) : 77 | $N = $feedwordpress->clear_cache(); 78 | $feeds = (($N == 1) ? __("feed") : __("feeds")); 79 | $this->updated = sprintf( __("Cleared %d cached %s from WordPress database."), $N, $feeds ); 80 | endif; 81 | 82 | } /* FeedWordPressPerformancePage::accept_POST () */ 83 | 84 | static function performance_box ($page, $box = NULL) { 85 | 86 | // Hey ho, let's go... 87 | ?> 88 | 89 | 90 | 91 | 94 | 95 | 96 | 97 | 111 | 112 | 113 | 114 |
    Feed cache: 92 |

    This will clear all cached copies of feed data from the WordPress database 93 | and force FeedWordPress to make a fresh scan for updates on syndicated feeds.

    Guid index: 98 | 99 |

    Creating this index may significantly improve performance on some large 100 | FeedWordPress installations.

    101 | 102 | 103 |

    You have already created an index on the guid column in the WordPress posts 104 | table. If you'd like to remove the index for any reason, you can do so here.

    105 | 106 | 107 | 108 | 109 | 110 |
    115 | display(); 121 | 122 | -------------------------------------------------------------------------------- /syndicatedpostterm.class.php: -------------------------------------------------------------------------------- 1 | post = $post; 9 | 10 | // Default to these 11 | $this->term = NULL; 12 | $this->tax = NULL; 13 | $this->exists = NULL; 14 | $this->exists_in = NULL; 15 | 16 | if (preg_match('/^{([^#}]*)#([0-9]+)}$/', $term, $backref)) : 17 | $cat_id = (int) $backref[2]; 18 | $tax = $backref[1]; 19 | if (strlen($tax) < 1) : 20 | $tax = $catTax; 21 | endif; 22 | 23 | $aTerm = get_term($cat_id, $tax); 24 | if ( !is_wp_error($aTerm) and !! $aTerm) : 25 | $this->exists = (array) $aTerm; 26 | $this->exists_in = $this->exists['taxonomy']; 27 | 28 | $this->term = $this->exists['name']; 29 | $this->tax = array($this->exists['taxonomy']); 30 | endif; 31 | 32 | else : 33 | $this->term = $term; 34 | $this->tax = $taxonomies; 35 | 36 | // Leave exists/exists_in empty until we search() 37 | 38 | endif; 39 | 40 | if (is_null($this->tax)) : 41 | $this->tax = array($catTax); 42 | endif; 43 | } /* SyndicatedPostTerm constructor */ 44 | 45 | public function is_familiar () { 46 | $ex = $this->exists; 47 | if (is_null($this->exists)) : 48 | $ex = $this->search(); 49 | endif; 50 | 51 | FeedWordPress::diagnostic( 52 | 'syndicated_posts:categories', 53 | 'Assigned category '.json_encode($this->term) 54 | .' by feed; checking '.json_encode($this->tax) 55 | . ' with result: '.json_encode($ex) 56 | ); 57 | return ( !is_wp_error($ex) and !! $ex); 58 | } /* SyndicatedPostTerm::familiar () */ 59 | 60 | protected function search () { 61 | 62 | // Initialize 63 | $found = null; 64 | 65 | // Either this is a numbered term code, which supplies the ID 66 | // and the taxonomy explicitly (e.g.: {category#2}; in which 67 | // case we have set $this->tax to a unit array containing only 68 | // the correct taxonomy, or else we have a term name and an 69 | // ordered array of taxonomies to search for that term name. In 70 | // either case, loop through and check each pair of term 71 | 72 | foreach ($this->tax as $tax) : 73 | 74 | if ( ! $this->is_forbidden_in($tax)) : 75 | 76 | $found = $this->fetch_record_in($tax); 77 | if ($found) : 78 | // When TRUE, the term has been found 79 | // and is now stored in $this->exists 80 | 81 | // Save the taxonomy we found this in. 82 | $this->exists_in = $tax; 83 | 84 | break; 85 | endif; 86 | 87 | endif; 88 | 89 | endforeach; 90 | 91 | FeedWordPress::diagnostic( 92 | 'syndicated_posts:categories:test', 93 | 'CHECKED familiarity of term ' 94 | .json_encode($this->term) 95 | .' across '.json_encode($this->tax) 96 | . ' with result: '.json_encode($found) 97 | ); 98 | 99 | return $this->exists; 100 | 101 | } /* SyndicatedPostTerm::search () */ 102 | 103 | protected function fetch_record_in ($tax) { 104 | $record = term_exists($this->term, $tax); 105 | 106 | FeedWordPress::diagnostic( 107 | 'syndicated_posts:categories:test', 108 | 'CHECK existence of '.$tax.': ' 109 | .json_encode($this->term) 110 | .' with result: '.json_encode($record) 111 | ); 112 | 113 | $found = ( !is_wp_error($record) and !! $record); 114 | 115 | if ($found) : 116 | $this->exists = $record; 117 | endif; 118 | 119 | return $found; 120 | } /* SyndicatedPostTerm::fetch_record_in() */ 121 | 122 | public function is_forbidden_in ($tax = NULL) { 123 | $forbid = false; // Innocent until proven guilty. 124 | 125 | $term = $this->term; 126 | if (is_null($tax) and (count($this->tax) > 0)) : 127 | $tax = $this->tax[0]; 128 | endif; 129 | 130 | if ($tax=='category' and strtolower($term)=='uncategorized') : 131 | $forbid = true; 132 | endif; 133 | 134 | // Run it through a filter. 135 | return apply_filters('syndicated_post_forbidden_term', $forbid, $term, $tax, $this->post); 136 | } /* SyndicatedPostTerm::is_forbidden_in () */ 137 | 138 | public function taxonomy () { 139 | if (is_null($this->exists_in)) : 140 | $this->search(); 141 | endif; 142 | 143 | return $this->exists_in; 144 | } /* SyndicatedPostTerm::taxonomy () */ 145 | 146 | public function id () { 147 | $term_id = NULL; 148 | 149 | if (is_null($this->exists)) : 150 | $this->search(); 151 | endif; 152 | 153 | $term = $this->exists; 154 | if (is_array($term) or is_object($term)) : 155 | 156 | // For hash tables of any sort, use the term_id member 157 | $term = (array) $term; 158 | $term_id = intval($term['term_id']); 159 | 160 | elseif (is_numeric($term)) : 161 | 162 | // For a straight numeric response, just return number 163 | $term_id = intval($term); 164 | 165 | endif; 166 | 167 | return $term_id; 168 | } /* SyndicatedPostTerm::id () */ 169 | 170 | public function insert ($tax = NULL) { 171 | $ret = NULL; 172 | 173 | if (is_null($tax)) : 174 | if (count($this->tax) > 0) : 175 | $tax = $this->tax[0]; 176 | endif; 177 | endif; 178 | 179 | if ( ! $this->is_forbidden_in($tax)) : 180 | $aTerm = wp_insert_term($this->term, $tax); 181 | if (is_wp_error($aTerm)) : 182 | 183 | // If debug mode is ON, this will halt us here. 184 | FeedWordPressDiagnostic::noncritical_bug( 185 | 'term insertion problem', array( 186 | 'term' => $this->term, 187 | 'result' => $aTerm, 188 | 'post' => $this->post, 189 | 'this' => $this 190 | ), __LINE__, __FILE__ 191 | ); 192 | 193 | // Otherwise, we'll continue & return NULL... 194 | 195 | else : 196 | $this->exists = $aTerm; 197 | $this->exists_in = $tax; 198 | 199 | $ret = $this->id(); 200 | endif; 201 | 202 | FeedWordPress::diagnostic( 203 | 'syndicated_posts:categories', 204 | 'CREATED unfamiliar '.$tax.': '.json_encode($this->term).' with result: '.json_encode($aTerm) 205 | ); 206 | else : 207 | FeedWordPress::diagnostic( 208 | 'syndicated_posts:categories', 209 | 'Category: DID NOT CREATE unfamiliar '.$tax.': '.json_encode($this->term).':' 210 | .' that '.$tax.' name is filtered out.' 211 | ); 212 | endif; 213 | 214 | return $ret; 215 | } /* SyndicatedPostTerm::insert () */ 216 | 217 | } /* class SyndicatedPostTerm */ 218 | 219 | -------------------------------------------------------------------------------- /syndicatedpostxpathquery.class.php: -------------------------------------------------------------------------------- 1 | $args); 24 | endif; 25 | 26 | $args = wp_parse_args($args, array( 27 | "path" => "", 28 | )); 29 | 30 | $this->setPath($args['path']); 31 | } /* SyndicatedPostXPathQuery::__construct() */ 32 | 33 | /** 34 | * SyndicatedPostXPathQuery::getPath 35 | * 36 | * @param array $args 37 | * @return mixed 38 | */ 39 | public function getPath ($args = array()) { 40 | $args = wp_parse_args($args, array( 41 | "parsed" => false, 42 | )); 43 | 44 | return ($args['parsed'] ? $this->parsedPath : $this->path); 45 | } /* SyndicatedPostXPathQuery::getPath () */ 46 | 47 | /** 48 | * SyndicatedPostXPathQuery::setPath 49 | * 50 | * @param string $path 51 | */ 52 | public function setPath ($path) { 53 | $this->urlHash = array(); 54 | 55 | $this->path = $path; 56 | 57 | // Allow {url} notation for namespaces. URLs will contain : and /, so... 58 | preg_match_all('/{([^}]+)}/', $path, $match, PREG_SET_ORDER); 59 | foreach ($match as $ref) : 60 | $this->urlHash[md5($ref[1])] = $ref[1]; 61 | endforeach; 62 | 63 | foreach ($this->urlHash as $hash => $url) : 64 | $path = str_replace('{'.$url.'}', '{#'.$hash.'}', $path); 65 | endforeach; 66 | 67 | $path = $this->parsePath(/*cur=*/ $path, /*orig=*/ $path); 68 | 69 | $this->parsedPath = $path; 70 | 71 | } /* SyndicatedPostXPathQuery::setPath() */ 72 | 73 | /** 74 | * SyndicatedPostXPathQuery::snipSlug 75 | * 76 | * @return string 77 | */ 78 | protected function snipSlug ($path, $start, $n) { 79 | $slug = substr($path, $start, ($n-$start)); 80 | if (strlen($slug) > 0) : 81 | if (preg_match('/{#([^}]+)}/', $slug, $ref)) : 82 | if (isset($this->urlHash[$ref[1]])) : 83 | $slug = str_replace( 84 | '{#'.$ref[1].'}', 85 | '{'.$this->urlHash[$ref[1]].'}', 86 | $slug 87 | ); 88 | endif; 89 | endif; 90 | endif; 91 | return $slug; 92 | } /* SyndicatedPostXPathQuery::snipSlug () */ 93 | 94 | /** 95 | * SyndicatedPostXPathQuery::parsePath () 96 | * 97 | * @param mixed $path 98 | * @param mixed $rootPath 99 | * @return array|object 100 | */ 101 | public function parsePath ($path, $rootPath) { 102 | if (is_array($path)) : 103 | // This looks like it's already been parsed. 104 | $pp = $path; 105 | else : 106 | $pp = array(); 107 | 108 | // Okay let's parse this thing. 109 | $n = 0; $start = 0; $state = 'slug'; 110 | while ($state != '$') : 111 | switch ($state) : 112 | case 'slash' : 113 | $slug = $this->snipSlug($path, $start, $n); 114 | if (strlen($slug) > 0) : 115 | $pp[] = $slug; 116 | endif; 117 | 118 | $n++; 119 | // don't include the slash in our next slug 120 | $start = $n; 121 | 122 | $state = (($n < strlen($path)) ? 'slug' : '$'); 123 | 124 | break; 125 | case 'brackets' : 126 | 127 | // first, snip off what we've consumed so far 128 | $slug = $this->snipSlug($path, $start, $n); 129 | if (strlen($slug) > 0) : 130 | $pp[] = $slug; 131 | endif; 132 | 133 | // now, chase the ] 134 | $depth = 1; 135 | $n++; $start = $n; 136 | 137 | // find the end of the [square-bracketed] expression 138 | while ($depth > 0 and $n != '') : 139 | $tok = ((strlen($path) > $n) ? $path[$n] : ''); 140 | switch ($tok) : 141 | case '' : 142 | // ERROR STATE: syntax error 143 | $depth = -1; 144 | $state = 'syntax-error'; 145 | break; 146 | case '[' : 147 | $depth++; 148 | break; 149 | case ']' : 150 | $depth--; 151 | break; 152 | default : 153 | // NOOP 154 | endswitch; 155 | $n++; 156 | endwhile; 157 | 158 | if ($state != 'syntax-error') : 159 | $bracketed = substr($path, $start, ($n-$start)-1); 160 | 161 | // recursive parsing 162 | $oFilter = new stdClass; 163 | $oFilter->verb = 'has'; 164 | $oFilter->query = $this->parsePath($bracketed, $rootPath); 165 | $pp[] = $oFilter; 166 | 167 | $start = $n; 168 | 169 | $state = 'slash-expected'; 170 | endif; 171 | break; 172 | 173 | case 'slash-expected' : 174 | $tok = ((strlen($path) > $n) ? $path[$n] : ''); 175 | if ($tok == '/' or $tok == '') : 176 | $state = 'slash'; 177 | else : 178 | $state = 'syntax-error'; 179 | endif; 180 | break; 181 | case 'syntax-error' : 182 | $pp = new WP_Error('xpath', __("Syntax error", "feedwordpress")); 183 | $state = '$'; 184 | break; 185 | case 'slug' : 186 | default : 187 | $tok = ((strlen($path) > $n) ? $path[$n] : ''); 188 | switch ($tok) : 189 | case '' : 190 | case '/' : 191 | $state = 'slash'; 192 | break; 193 | case '[' : 194 | $state = 'brackets'; 195 | break; 196 | default : 197 | $n++; 198 | endswitch; 199 | endswitch; 200 | endwhile; 201 | endif; 202 | return $pp; 203 | } /* SyndicatedPostXPathQuery::parsePath() */ 204 | 205 | /** 206 | * SyndicatedPostXPathQuery::match 207 | * 208 | * @param string $path 209 | * @return array 210 | */ 211 | public function match ($r = array()) { 212 | $path = $this->parsedPath; 213 | 214 | $r = wp_parse_args($r, array( 215 | "type" => SIMPLEPIE_TYPE_ATOM_10, 216 | "xmlns" => array(), 217 | "map" => array(), 218 | "context" => array(), 219 | "parent" => array(), 220 | "format" => "string", 221 | )); 222 | 223 | $this->feed_type = $r['type']; 224 | $this->xmlns = $r['xmlns']; 225 | 226 | // Start out with a get_item_tags query. 227 | $node = ''; 228 | while (strlen($node)==0 and !is_null($node)) : 229 | $node = array_shift($path); 230 | endwhile; 231 | 232 | if (is_string($node) and isset($r['map'][$node])) : 233 | $data = $r['map'][$node]; 234 | $node = array_shift($path); 235 | else : 236 | $data = $r['map']['/']; 237 | endif; 238 | 239 | $matches = $data; 240 | while ( !is_null($node)) : 241 | if (is_object($node) OR strlen($node) > 0) : 242 | list($axis, $element) = $this->xpath_name_and_axis($node); 243 | if ('self'==$axis) : 244 | if (is_object($element) and property_exists($element, 'verb')) : 245 | 246 | $subq = new self(array("path" => $element->query)); 247 | $result = $subq->match(array( 248 | "type" => $r['type'], 249 | "xmlns" => $r['xmlns'], 250 | "map" => array( 251 | "/" => $matches, 252 | ), 253 | "context" => $matches, 254 | "parent" => $r['parent'], 255 | "format" => "object", 256 | )); 257 | 258 | // when format = 'object' we should get back 259 | // a sparse array of arrays, with indices = indices 260 | // from the input array, each element = an array of 261 | // one or more matching elements 262 | 263 | if ($element->verb = 'has' and is_array($result)) : 264 | 265 | $results = array(); 266 | foreach (array_keys($result) as $a) : 267 | $results[$a] = $matches[$a]; 268 | endforeach; 269 | 270 | $matches = $results; 271 | $data = $matches; 272 | endif; 273 | 274 | elseif (is_numeric($node)) : 275 | 276 | // according to W3C, sequence starts at position 1, not 0 277 | // so subtract 1 to line up with PHP array starting at 0 278 | $idx = intval($element) - 1; 279 | if (isset($matches[$idx])) : 280 | $data = array($idx => $matches[$idx]); 281 | else : 282 | $data = array(); 283 | endif; 284 | 285 | $matches = array($idx => $data); 286 | endif; 287 | 288 | else : 289 | $matches = array(); 290 | 291 | foreach ($data as $idx => $datum) : 292 | if ( !is_string($datum) and isset($datum[$axis])) : 293 | foreach ($datum[$axis] as $ns => $elements) : 294 | if (isset($elements[$element])) : 295 | // Potential match. 296 | // Check namespace. 297 | if (is_string($elements[$element])) : // Attribute 298 | $addenda = array($elements[$element]); 299 | $contexts = array($datum); 300 | 301 | // Element 302 | else : 303 | $addenda = $elements[$element]; 304 | $contexts = $elements[$element]; 305 | endif; 306 | 307 | foreach ($addenda as $index => $addendum) : 308 | $context = $contexts[$index]; 309 | 310 | $namespaces = $this->xpath_possible_namespaces($node, $context); 311 | if (in_array($ns, $namespaces)) : 312 | $matches[] = $addendum; 313 | endif; 314 | endforeach; 315 | endif; 316 | endforeach; 317 | endif; 318 | endforeach; 319 | 320 | $data = $matches; 321 | endif; 322 | endif; 323 | $node = array_shift($path); 324 | endwhile; 325 | 326 | $matches = array(); 327 | foreach ($data as $idx => $datum) : 328 | if ($r['format'] == 'string') : 329 | if (is_string($datum)) : 330 | $matches[] = $datum; 331 | elseif (isset($datum['data'])) : 332 | $matches[] = $datum['data']; 333 | endif; 334 | else : 335 | $matches[$idx] = $datum; 336 | endif; 337 | endforeach; 338 | 339 | return $matches; 340 | } /* SyndicatedPostXPathQuery::match() */ 341 | 342 | public function xpath_default_namespace () { 343 | // Get the default namespace. 344 | $type = $this->feed_type; 345 | if ($type & SIMPLEPIE_TYPE_ATOM_10) : 346 | $defaultNS = SIMPLEPIE_NAMESPACE_ATOM_10; 347 | elseif ($type & SIMPLEPIE_TYPE_ATOM_03) : 348 | $defaultNS = SIMPLEPIE_NAMESPACE_ATOM_03; 349 | elseif ($type & SIMPLEPIE_TYPE_RSS_090) : 350 | $defaultNS = SIMPLEPIE_NAMESPACE_RSS_090; 351 | elseif ($type & SIMPLEPIE_TYPE_RSS_10) : 352 | $defaultNS = SIMPLEPIE_NAMESPACE_RSS_10; 353 | elseif ($type & SIMPLEPIE_TYPE_RSS_20) : 354 | $defaultNS = SIMPLEPIE_NAMESPACE_RSS_20; 355 | else : 356 | $defaultNS = SIMPLEPIE_NAMESPACE_RSS_20; 357 | endif; 358 | return $defaultNS; 359 | } /* SyndicatedPostXPathQuery::xpath_default_namespace() */ 360 | 361 | public function xpath_name_and_axis ($node) { 362 | // $ns = NULL; // Was unused. (gwyneth 20230920) 363 | $element = NULL; 364 | 365 | $axis = 'child'; // "In effect, `child` is the default axis." 366 | if (is_object($node) and property_exists($node, 'verb')): 367 | if ('has'==$node->verb) : 368 | $axis = 'self'; 369 | endif; 370 | elseif (strpos($node, '::') !== false) : 371 | list($axis, $node) = explode("::", $node, 2); 372 | if ($axis=='attribute') : 373 | $axis = 'attribs'; // map from W3C to SimplePie's idiosyncratic notation 374 | endif; 375 | elseif (substr($node, 0, 1)=='@') : 376 | $axis = 'attribs'; $node = substr($node, 1); 377 | elseif (is_numeric($node)) : 378 | $axis = 'self'; 379 | elseif (substr($node, 0, 1)=='/') : 380 | // FIXME: properly, we should check for // and if we have it, 381 | // treat that as short for /descendent-or-self::node()/ 382 | $axis = 'child'; $node = substr($node, 1); 383 | else : 384 | // NOOP 385 | endif; 386 | 387 | if (is_string($node) and preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) : 388 | $element = $ref[2]; 389 | elseif (is_string($node) and strpos($node, ':') !== FALSE) : 390 | list($xmlns, $element) = explode(':', $node, 2); 391 | else : 392 | $element = $node; 393 | endif; 394 | return array($axis, $element); 395 | } /* SyndicatedPostXPathQuery::xpath_name_and_axis () */ 396 | 397 | public function xpath_possible_namespaces ($node, $datum = array()) { 398 | $ns = NULL; 399 | // $element = NULL; // reverse of before: now it's the $element that's never used (gwyneth 20230920) 400 | 401 | // Is $attr really the correct thing to assign to? It's never used... (gwyneth 20230920) 402 | if (substr($node, 0, 1)=='@') : 403 | $attr = '@'; $node = substr($node, 1); 404 | else : 405 | $attr = ''; 406 | endif; 407 | 408 | if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) : 409 | $ns = array($ref[1]); 410 | elseif (strpos($node, ':') !== FALSE) : 411 | list($xmlns, $element) = explode(':', $node, 2); 412 | 413 | if (isset($this->xmlns['reverse'][$xmlns])) : 414 | $ns = $this->xmlns['reverse'][$xmlns]; 415 | else : 416 | $ns = array($xmlns); 417 | endif; 418 | 419 | // Fucking SimplePie. For attributes in default xmlns. 420 | $defaultNS = $this->xpath_default_namespace(); 421 | if (isset($this->xmlns['forward'][$defaultNS]) 422 | and ($xmlns==$this->xmlns['forward'][$defaultNS])) : 423 | $ns[] = ''; 424 | endif; 425 | 426 | if (isset($datum['xmlns'])) : 427 | if (isset($datum['xmlns'][$xmlns])) : 428 | $ns[] = $datum['xmlns'][$xmlns]; 429 | endif; 430 | endif; 431 | else : 432 | // Often in SimplePie, the default namespace gets stored 433 | // as an empty string rather than a URL. 434 | $ns = array($this->xpath_default_namespace(), ''); 435 | endif; 436 | return array_unique($ns); 437 | } /* SyndicatedPostXPathQuery::xpath_possible_namespaces() */ 438 | 439 | } /* class SyndicatedPostXPathQuery */ 440 | 441 | // When called directly, run through and perform some tests. 442 | if (basename($_SERVER['SCRIPT_FILENAME'])==basename(__FILE__)) : 443 | # some day when I am a grown-up developer I might include 444 | # some test cases in this here section 445 | # we need to implement wp_parse_args(), __(), and class WP_Error ... 446 | #function wp_parse_args ($r, $defaults) { 447 | # return array_merge($defaults, $r); 448 | #} 449 | #function __($text, $domain) { 450 | # return $text; 451 | #} 452 | #class WP_Error { 453 | # public function __construct ( $slug, $message ) { 454 | # /*DBG*/ echo $slug; 455 | # /*DBG*/ echo ": "; 456 | # /*DBG*/ echo $message; 457 | # } 458 | #} 459 | # 460 | #header("Content-type: text/plain"); 461 | # 462 | #$spxq = new SyndicatedPostXPathQuery(array("path" => $_REQUEST['p'])); 463 | # 464 | #var_dump($spxq); 465 | endif; 466 | -------------------------------------------------------------------------------- /syndication.php: -------------------------------------------------------------------------------- 1 | display(); 6 | -------------------------------------------------------------------------------- /syndicationdataqueries.class.php: -------------------------------------------------------------------------------- 1 | get('guid')) : 19 | $q->is_single = false; // Causes nasty side-effects. 20 | $q->is_singular = true; // Doesn't? 21 | endif; 22 | 23 | $ff = $q->get('fields'); 24 | if ($ff == '_synfresh' or $ff == '_synfrom') : 25 | $q->query_vars['cache_results'] = false; // Not suitable. 26 | endif; 27 | } /* SyndicationDataQueries::parse_query () */ 28 | 29 | function pre_get_posts ($q) { 30 | // Is this a stub? Nothing is used... (gwyneth 20230920) 31 | } 32 | 33 | function posts_request ($sql, $query) { 34 | if ($query->get('fields') == '_synfresh') : 35 | FeedWordPress::diagnostic('feed_items:freshness:sql', "SQL: ".$sql); 36 | endif; 37 | return $sql; 38 | } 39 | 40 | function posts_search ($search, $query) { 41 | global $wpdb; 42 | if ($guid = $query->get('guid')) : 43 | if (strlen(trim($guid)) > 0) : 44 | $seek = array($guid); 45 | 46 | // MD5 hashes 47 | if (preg_match('/^[0-9a-f]{32}$/i', $guid)) : 48 | $seek[] = SyndicatedPost::normalize_guid_prefix().$guid; 49 | $seek[] = SyndicatedPost::alternative_guid_prefix().$guid; 50 | endif; 51 | 52 | // Invalid URIs, URIs that WordPress just doesn't like, and URIs 53 | // that WordPress decides to munge. 54 | $nGuid = SyndicatedPost::normalize_guid($guid); 55 | if ($guid != $nGuid) : 56 | $seek[] = $nGuid; 57 | $seek[] = SyndicatedPost::alternative_guid($guid); 58 | endif; 59 | 60 | // Escape to prevent frak-ups, injections, etc. 61 | $seek = array_map('esc_sql', $seek); 62 | 63 | // Assemble 64 | $guidMatch = "(guid = '".implode("') OR (guid = '", $seek)."')"; 65 | $search .= " AND ($guidMatch)"; 66 | endif; 67 | endif; 68 | 69 | if ($query->get('fields')=='_synfresh') : 70 | // Ugly hack to ensure we ONLY check by guid in syndicated freshness 71 | // checks -- for reasons of both performance and correctness. Pitch: 72 | $search .= " -- '"; 73 | elseif ($query->get('fields')=='_synfrom') : 74 | $search .= " AND ({$wpdb->postmeta}.meta_key = '".$query->get('meta_key')."' AND {$wpdb->postmeta}.meta_value = '".$query->get('meta_value')."') -- '"; 75 | endif; 76 | return $search; 77 | } /* SyndicationDataQueries::posts_search () */ 78 | 79 | function posts_where ($where, $q) { 80 | global $wpdb; 81 | 82 | // Ugly hack to ensure we ONLY check by guid in syndicated freshness 83 | // checks -- for reasons of both performance and correctness. Catch: 84 | if (strpos($where, " -- '") !== false) : 85 | $bits = explode(" -- '", $where, 2); 86 | $where = $bits[0]; 87 | endif; 88 | 89 | if ($psn = $q->get('post_status__not')) : 90 | $where .= " AND ({$wpdb->posts}.post_status <> '".esc_sql($psn)."')"; 91 | endif; 92 | 93 | return $where; 94 | } /* SyndicationDataQueries::post_where () */ 95 | 96 | function posts_fields ($fields, $query) { 97 | global $wpdb; 98 | if ($f = $query->get('fields')) : 99 | switch ($f) : 100 | case '_synfresh' : 101 | $fields = "{$wpdb->posts}.ID, {$wpdb->posts}.guid, {$wpdb->posts}.post_modified_gmt, {$wpdb->posts}.post_name"; 102 | break; 103 | case '_synfrom' : 104 | $fields = "{$wpdb->posts}.ID, {$wpdb->posts}.guid, {$wpdb->posts}.post_title, {$wpdb->postmeta}.meta_value"; 105 | break; 106 | default : 107 | // Do nothing. 108 | endswitch; 109 | endif; 110 | return $fields; 111 | } /* SyndicationDataQueries::posts_fields () */ 112 | } 113 | 114 | $SDQ = new SyndicationDataQueries; 115 | 116 | -------------------------------------------------------------------------------- /template-functions.php: -------------------------------------------------------------------------------- 1 | is_syndicated(); 18 | } /* function is_syndicated() */ 19 | 20 | /** 21 | * feedwordpress_display_url: format a fully-formed URL for display in the 22 | * FeedWordPress admin interface, abbreviating it (e.g.: input of 23 | * `http://feedwordpress.radgeek.com/feed/` will be shortened to 24 | * `feedwordpress.radgeek.com/feed/`) 25 | * 26 | * @param string $url provides the URL to display 27 | * @param int $before a number of characters to preserve from the beginning of the URL if it must be shortened 28 | * @param int $after a number of characters to preserve from the end of the URL if it must be shortened 29 | * @return string containing an abbreviated display form of the URL (e.g.: `feedwordpress.radgeek.net/feed`) 30 | */ 31 | function feedwordpress_display_url ($url, $before = 60, $after = 0) { 32 | $bits = parse_url($url); 33 | 34 | // Strip out crufty subdomains 35 | if (isset($bits['host'])) : 36 | $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']); 37 | endif; 38 | 39 | // Reassemble bit-by-bit with minimum of crufty elements 40 | $url = (isset($bits['user'])?$bits['user'].'@':'') 41 | .(isset($bits['host'])?$bits['host']:'') 42 | .(isset($bits['path'])?$bits['path']:'') 43 | .(isset($uri_bits['port'])?':'.$uri_bits['port']:'') 44 | .(isset($bits['query'])?'?'.$bits['query']:''); 45 | 46 | if (strlen($url) > ($before+$after)) : 47 | $url = substr($url, 0, $before).'…'.substr($url, 0 - $after, $after); 48 | endif; 49 | 50 | return $url; 51 | } /* feedwordpress_display_url () */ 52 | 53 | function get_syndication_source_property ($original, $id, $local, $remote = NULL) { 54 | $p = new FeedWordPressLocalPost($id); 55 | return $p->meta($local, array("unproxy" => $original, "unproxied setting" => $remote)); 56 | } /* function get_syndication_source_property () */ 57 | 58 | function get_syndication_source_link ($original = NULL, $id = NULL) { 59 | $p = new FeedWordPressLocalPost($id); 60 | return $p->syndication_source_link($original); 61 | } /* function get_syndication_source_link() */ 62 | 63 | function the_syndication_source_link ($original = NULL, $id = NULL) { 64 | echo esc_url( get_syndication_source_link($original, $id) ); 65 | } /* function the_syndication_source_link() */ 66 | 67 | function get_syndication_source ($original = NULL, $id = NULL) { 68 | $p = new FeedWordPressLocalPost($id); 69 | return $p->syndication_source($original); 70 | } /* function get_syndication_source() */ 71 | 72 | function the_syndication_source ($original = NULL, $id = NULL) { 73 | echo esc_html( get_syndication_source($original, $id) ); 74 | } /* function the_syndication_source () */ 75 | 76 | function get_syndication_feed ($original = NULL, $id = NULL) { 77 | $p = new FeedWordPressLocalPost($id); 78 | return $p->syndication_feed($original); 79 | } /* function get_syndication_feed() */ 80 | 81 | function the_syndication_feed ($original = NULL, $id = NULL) { 82 | echo esc_url( get_syndication_feed($original, $id) ); 83 | } /* function the_syndication_feed() */ 84 | 85 | function get_syndication_feed_guid ($original = NULL, $id = NULL) { 86 | $p = new FeedWordPressLocalPost($id); 87 | return $p->syndication_feed_guid( $original ); 88 | } /* function get_syndication_feed_guid () */ 89 | 90 | function the_syndication_feed_guid ($original = NULL, $id = NULL) { 91 | echo esc_html( get_syndication_feed_guid( $original, $id ) ); 92 | } /* function the_syndication_feed_guid () */ 93 | 94 | function get_syndication_feed_id ($id = NULL) { 95 | $p = new FeedWordPressLocalPost($id); 96 | return $p->feed_id(); 97 | } /* function get_syndication_feed_id () */ 98 | 99 | function the_syndication_feed_id ($id = NULL) { 100 | echo esc_html( get_syndication_feed_id($id) ); 101 | } /* function the_syndication_feed_id () */ 102 | 103 | function get_syndication_feed_object ($id = NULL) { 104 | $p = new FeedWordPressLocalPost($id); 105 | return $p->feed(); 106 | } /* function get_syndication_feed_object() */ 107 | 108 | function get_feed_meta ($key, $id = NULL) { 109 | $ret = NULL; 110 | 111 | $link = get_syndication_feed_object($id); 112 | if (is_object($link) and isset($link->settings[$key])) : 113 | $ret = $link->settings[$key]; 114 | endif; 115 | return $ret; 116 | } /* function get_feed_meta() */ 117 | 118 | function get_syndication_permalink ($id = NULL) { 119 | $p = new FeedWordPressLocalPost($id); 120 | return $p->syndication_permalink(); 121 | } /* function get_syndication_permalink () */ 122 | 123 | function the_syndication_permalink ($id = NULL) { 124 | echo esc_url( get_syndication_permalink($id) ); 125 | } /* function the_syndication_permalink () */ 126 | 127 | /** 128 | * get_local_permalink: returns a string containing the internal permalink 129 | * for a post (whether syndicated or not) on your local WordPress installation. 130 | * This may be useful if you want permalinks to point to the original source of 131 | * an article for most purposes, but want to retrieve a URL for the local 132 | * representation of the post for one or two limited purposes (for example, 133 | * linking to a comments page on your local aggregator site). 134 | * 135 | * @param $id The numerical ID of the post to get the permalink for. If empty, 136 | * defaults to the current post in a Loop context. 137 | * @return string The URL of the local permalink for this post. 138 | * 139 | * @uses get_permalink() 140 | * @global $feedwordpress_the_original_permalink 141 | * 142 | * @since 2010.0217 143 | */ 144 | function get_local_permalink ( $id = NULL ) { 145 | global $feedwordpress_the_original_permalink; 146 | 147 | // get permalink, and thus activate filter and force global to be filled 148 | // with original URL. 149 | $url = get_permalink( $id ); 150 | return $feedwordpress_the_original_permalink; 151 | } /* get_local_permalink() */ 152 | 153 | /** 154 | * the_original_permalink: displays the contents of get_original_permalink() 155 | * 156 | * @param $id The numerical ID of the post to get the permalink for. If empty, 157 | * defaults to the current post in a Loop context. 158 | * 159 | * @uses get_local_permalinks() 160 | * @uses apply_filters 161 | * 162 | * @since 2010.0217 163 | */ 164 | function the_local_permalink ( $id = NULL ) { 165 | print esc_url( apply_filters( 'the_permalink', get_local_permalink( $id ) ) ); 166 | } /* function the_local_permalink() */ 167 | 168 | -------------------------------------------------------------------------------- /templates/notice-debug-mode-yes.html.php: -------------------------------------------------------------------------------- 1 |
    2 |

    FeedWordPress warning. Debugging mode is ON. 3 | While it remains on, FeedWordPress displays many diagnostic error messages, 4 | warnings, and notices that are ordinarily suppressed, and also turns off all 5 | caching of feeds. Use with caution: this setting is absolutely inappropriate 6 | for a production server.

    7 |
    8 | -------------------------------------------------------------------------------- /updatedpostscontrol.class.php: -------------------------------------------------------------------------------- 1 | page =& $page; 6 | } /* UpdatedPostsControl constructor */ 7 | 8 | function UpdatedPostsControl( &$page ) { 9 | self::__construct( $page ); 10 | } 11 | 12 | function display () { 13 | $settings = array( 14 | // This is all bass-ackwards because the actual yes/no 15 | // setting is whether to *freeze* posts out of being 16 | // updated, not whether to *expose* it to being updated, 17 | // but in the UI we ask whether the user wants to 18 | // *expose* it. I have my reasons. Stop judging me! 19 | 'no' => __('Yes, update the syndicated copy to match'), 20 | 'yes' => __('No, leave the syndicated copy unmodified'), 21 | ); 22 | $params = array( 23 | 'setting-default' => 'default', 24 | 'global-setting-default' => 'no', 25 | 'labels' => array('yes' => 'leave unmodified', 'no' => 'update to match'), 26 | 'default-input-value' => 'default', 27 | ); 28 | 29 | if ($this->page->for_feed_settings()) : 30 | $aFeed = 'this feed'; 31 | else : 32 | $aFeed = 'a syndicated feed'; 33 | endif; 34 | ?> 35 | 36 | 37 |

    When includes updated content for 38 | a post that was already syndicated, should the syndicated copy 39 | of the post be updated to match the revised version?

    40 | 41 | page->setting_radio_control( 43 | 'freeze updates', 'freeze_updates', 44 | $settings, $params 45 | ); 46 | ?> 47 | 48 | 49 | page->for_feed_settings()) : 54 | if ( ! is_null( FeedWordPress::post( 'freeze_updates' ) ) ) : 55 | $this->page->link->settings['freeze updates'] = FeedWordPress::post( 'freeze_updates' ); 56 | endif; 57 | else : 58 | // Updated posts 59 | if ( ! is_null( FeedWordPress::post( 'freeze_updates' ) ) ) : 60 | update_option('feedwordpress_freeze_updates', FeedWordPress::post( 'freeze_updates' )); 61 | endif; 62 | endif; 63 | } /* UpdatedPostsControl::accept_POST() */ 64 | } /* class UpdatedPostsControl */ 65 | 66 | 67 | --------------------------------------------------------------------------------