You've already forked wc-licensed-product
Release v0.2.0 - Security and integrity features
- Add REST API response signing using HMAC-SHA256 - Add SHA256 hash validation for version file uploads - Add ResponseSigner class for automatic API response signing - Add file_hash column to database schema - Remove external URL support from version uploads - Update translations with all fuzzy strings resolved Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -92,16 +92,27 @@ class VersionManager
|
||||
|
||||
/**
|
||||
* Create a new version
|
||||
*
|
||||
* @throws \InvalidArgumentException If file hash validation fails
|
||||
*/
|
||||
public function createVersion(
|
||||
int $productId,
|
||||
string $version,
|
||||
?string $releaseNotes = null,
|
||||
?string $downloadUrl = null,
|
||||
?int $attachmentId = null
|
||||
?int $attachmentId = null,
|
||||
?string $fileHash = null
|
||||
): ?ProductVersion {
|
||||
global $wpdb;
|
||||
|
||||
// Validate file hash if both attachment and hash are provided
|
||||
if ($attachmentId !== null && $attachmentId > 0 && $fileHash !== null && $fileHash !== '') {
|
||||
$validatedHash = $this->validateFileHash($attachmentId, $fileHash);
|
||||
if ($validatedHash === false) {
|
||||
return null;
|
||||
}
|
||||
$fileHash = $validatedHash;
|
||||
}
|
||||
|
||||
$parsed = ProductVersion::parseVersion($version);
|
||||
|
||||
$tableName = Installer::getVersionsTable();
|
||||
@@ -114,10 +125,9 @@ class VersionManager
|
||||
'minor_version' => $parsed['minor'],
|
||||
'patch_version' => $parsed['patch'],
|
||||
'release_notes' => $releaseNotes,
|
||||
'download_url' => $downloadUrl,
|
||||
'is_active' => 1,
|
||||
];
|
||||
$formats = ['%d', '%s', '%d', '%d', '%d', '%s', '%s', '%d'];
|
||||
$formats = ['%d', '%s', '%d', '%d', '%d', '%s', '%d'];
|
||||
|
||||
// Only include attachment_id if it's set
|
||||
if ($attachmentId !== null && $attachmentId > 0) {
|
||||
@@ -125,6 +135,12 @@ class VersionManager
|
||||
$formats[] = '%d';
|
||||
}
|
||||
|
||||
// Only include file_hash if it's set
|
||||
if ($fileHash !== null && $fileHash !== '') {
|
||||
$data['file_hash'] = $fileHash;
|
||||
$formats[] = '%s';
|
||||
}
|
||||
|
||||
$result = $wpdb->insert($tableName, $data, $formats);
|
||||
|
||||
if ($result === false) {
|
||||
@@ -136,13 +152,44 @@ class VersionManager
|
||||
return $this->getVersionById((int) $wpdb->insert_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate file hash against attachment
|
||||
*
|
||||
* @return string|false The validated hash (lowercase) or false on mismatch
|
||||
* @throws \InvalidArgumentException If hash doesn't match
|
||||
*/
|
||||
private function validateFileHash(int $attachmentId, string $providedHash): string|false
|
||||
{
|
||||
$filePath = get_attached_file($attachmentId);
|
||||
if (!$filePath || !file_exists($filePath)) {
|
||||
throw new \InvalidArgumentException(
|
||||
__('Attachment file not found.', 'wc-licensed-product')
|
||||
);
|
||||
}
|
||||
|
||||
$calculatedHash = hash_file('sha256', $filePath);
|
||||
$providedHash = strtolower(trim($providedHash));
|
||||
|
||||
if (!hash_equals($calculatedHash, $providedHash)) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
/* translators: 1: provided hash, 2: calculated hash */
|
||||
__('File checksum does not match. Expected: %1$s, Got: %2$s', 'wc-licensed-product'),
|
||||
$providedHash,
|
||||
$calculatedHash
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $calculatedHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a version
|
||||
*/
|
||||
public function updateVersion(
|
||||
int $versionId,
|
||||
?string $releaseNotes = null,
|
||||
?string $downloadUrl = null,
|
||||
?bool $isActive = null,
|
||||
?int $attachmentId = null
|
||||
): bool {
|
||||
@@ -156,11 +203,6 @@ class VersionManager
|
||||
$formats[] = '%s';
|
||||
}
|
||||
|
||||
if ($downloadUrl !== null) {
|
||||
$data['download_url'] = $downloadUrl;
|
||||
$formats[] = '%s';
|
||||
}
|
||||
|
||||
if ($isActive !== null) {
|
||||
$data['is_active'] = $isActive ? 1 : 0;
|
||||
$formats[] = '%d';
|
||||
|
||||
Reference in New Issue
Block a user